package com.xbongbong.paas.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.ExcelConstant;
import com.xbongbong.paas.constant.FieldAttrConstant;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.DownloadExcelTypeEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.RelativeProductImportEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.pojo.ExcelLogPojo;
import com.xbongbong.paas.pojo.ExportExplainPojo;
import com.xbongbong.paas.pojo.ExportStatusPojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.KeyValuePojo;
import com.xbongbong.paas.pojo.dto.ExcelTemplateDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.vo.ExportFormDataVO;
import com.xbongbong.paas.pojo.vo.LinkResultDataDTO;
import com.xbongbong.paas.pojo.vo.LinkResultDataVO;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.service.ExcelDataService;
import com.xbongbong.paas.service.ExcelLogService;
import com.xbongbong.paas.service.ExcelOperatorService;
import com.xbongbong.paas.service.HandleImportService;
import com.xbongbong.paas.service.PaasAppService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.ReflectHelper;
import com.xbongbong.paas.toolbox.thread.TransmittableThreadLocalUtil;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.ItemUtil;
import com.xbongbong.parent.parse.data.BaseFormDataLinkDataHelp;
import com.xbongbong.parent.parse.data.FormDataListAnalysisDataHelp;
import com.xbongbong.parent.parse.data.LinkDataHelp;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.customerstatement.pojo.StatementTableDataExportPojo;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.export.pojo.ExportLinkDataPojo;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.onlineEditor.OnlineEditorMap4ExportPojo;
import com.xbongbong.pro.webexport.dto.CustomerStatementExportDTO;
import com.xbongbong.pro.webexport.dto.SignExportDTO;
import com.xbongbong.pro.webexport.dto.SignInExportDTO;
import com.xbongbong.pro.webexport.dto.SpecialWorkOrderExportDTO;
import com.xbongbong.pro.webimport.LinkFormImportPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StockConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.constant.export.ImportConstant;
import com.xbongbong.saas.domain.entity.PublicGroupSeniorEntity;
import com.xbongbong.saas.domain.entity.UserAndDepTeamEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.ext.SignInEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkOrderEntityExt;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.CustomerStatementEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.UserTeamEnum;
import com.xbongbong.saas.enums.VisibleRangeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CompetitorEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.WaitOutstockEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.enums.product.WorkOrderProductEnum;
import com.xbongbong.saas.enums.subform.SubFormTransferEnum;
import com.xbongbong.saas.enums.subform.VisibleRangeTeamEnum;
import com.xbongbong.saas.help.DistributorListHelp;
import com.xbongbong.saas.help.FormDataAnalysisHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.service.DistributorAccountService;
import com.xbongbong.saas.service.PublicGroupSeniorService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * excel导入导出help
 * @author 魏荣杰
 * @date 2019/12/27 2:48 下午
 * @since v4.9.0
 * @version v4.9.0
 */
@Component
public class PaasExcelExportHelp {
    private static final Logger LOG = LoggerFactory.getLogger(PaasExcelExportHelp.class);

    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private HandleImportService handleImportService;
    @Resource
    private EsHelper esHelper;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private ExcelOperatorService excelOperatorService;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private UserModel userModel;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private BaseFormDataLinkDataHelp baseFormDataLinkDataHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private PaasAppService paasAppService;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private LinkDataHelp linkDataHelp;
    @Resource
    private DistributorListHelp distributorListHelp;
    @Resource
    private DistributorAccountService distributorAccountService;
    @Resource
    private IndexTypeModel indexTypeModel;
    @Resource
    private UserTeamHelp userTeamHelp;
    @Resource
    private PublicGroupSeniorService publicGroupSeniorService;
    @Resource
    private ExportExcelExplainHelp exportExcelExplainHelp;
    @Resource
    private ExcelDataService excelDataService;
    @Resource
    private ExcelLogService excelLogService;
    @Resource
    private FormDataAnalysisHelp formDataAnalysisHelp;
    @Resource
    private OnlineEditorHelp onlineEditorHelp;

    @Async(value = "exportThreadPool")
    public ExportFormDataVO exportSaasFormData(FormDataListDTO formDataListDTO, PaasFormDataEsListVO formDataListVO) throws XbbException {
        String[] split = formDataListDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        ExportFormDataVO exportFormDataVO = new ExportFormDataVO();
        String hashKey = formDataListDTO.getCorpid() + "_" + formDataListDTO.getUserId();
        Workbook workbook = null;
        try {
            String corpid = formDataListDTO.getCorpid();
            Integer businessType = formDataListDTO.getBusinessType();
            ExcelTemplateDTO excelTemplateDTO = new ExcelTemplateDTO();
            BeanUtil.copyProperties(formDataListDTO, excelTemplateDTO);

            ExportExplainPojo exportExplainPojo = exportExcelExplainHelp.getExportExplain(formDataListDTO, formDataListVO);

            PaasMenuEntity paasMenuEntity = exportExplainPojo.getPaasMenuEntity();
            PaasFormExplainEntity paasFormExplainEntity = exportExplainPojo.getPaasFormExplainEntity();
            List<FieldAttrEntityForImport> fieldAttr = exportExplainPojo.getFieldAttr();

            //查看是否启用多单位公司级配置
            CompanyConfigEntity configEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.ENABLE_MULTI_UNIT.getAlias(), corpid);

            String menuName = paasMenuEntity.getName();

            // 处理字段解释，有一些转换是在这里面处理的
            ExportExplainPojo dataExplainPojo = exportExcelExplainHelp.dealExplain(formDataListDTO, paasFormExplainEntity, fieldAttr, excelTemplateDTO);
            JSONArray dataExplain = dataExplainPojo.getDataExplain();
            fieldAttr = dataExplainPojo.getFieldAttr();
            // 导入状态实体封装
            ExportStatusPojo exportStatusPojo = new ExportStatusPojo(formDataListDTO.getAppId(), formDataListDTO.getFormId(), formDataListDTO.getMenuId(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType());
            exportStatusPojo.setTotalNum(formDataListVO.getPaasFormDataESList().size());
            // 解析数据
            formatDataValue(formDataListDTO, fieldAttr, excelTemplateDTO, formDataListVO, configEntity, exportStatusPojo);

            List<PaasFormDataEntityExt> paasFormDataESList = formDataListVO.getPaasFormDataESList();
            if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.STOCK_SEARCH.getCode())) {
                menuName = XbbRefTypeEnum.STOCK_SEARCH.getName();
            } else if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.WARNING_SEARCH.getCode())) {
                menuName = XbbRefTypeEnum.WARNING_SEARCH.getName();
            } else if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.GUARANTEE_SEARCH.getCode())) {
                menuName = XbbRefTypeEnum.GUARANTEE_SEARCH.getName();
            }
            LOG.warn("let_me_see_see_exportSaasFormData1" + corpid + " size: " + paasFormDataESList.size());
            if (CollectionsUtil.isEmpty(paasFormDataESList)) {
                workbook = excelOperatorService.createExcelTemplate(formDataListDTO.getBusinessType(), dataExplain, menuName, DownloadExcelTypeEnum.TEMPLATE.getType(), 0, false);
            } else {
                workbook = excelOperatorService.createExcel(paasFormDataESList, dataExplain, menuName, formDataListDTO);
            }
            LOG.warn("letMeSeeSeeexportSaasFormData3" + corpid + " size: " + paasFormDataESList.size());
            String excelName = menuName + DateTimeUtil.getString(DateTimeUtil.SDFDate) + ImportConstant.EXCEL_SUFFIX;
            exportFormDataVO.setWorkbook(workbook);
            exportFormDataVO.setName(excelName);
            LOG.warn("let_me_see_see_exportSaasFormData2" + corpid + " size: " + paasFormDataESList.size());
            // OSS上传文件
            handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);
        } catch (XbbException e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportSaasFormData error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw e;
        } catch (Exception e) {
            LOG.error("paasExcel数据库导出表单数据出错", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        } finally {
            closeWorkBookException(workbook);
        }
        return exportFormDataVO;
    }

    @Async(value = "exportThreadPool")
    public ExportFormDataVO exportSaasFormData(FormDataListDTO formDataListDTO, Integer businessType, boolean partialExportFlag ) throws XbbException {
        String corpid = formDataListDTO.getCorpid();
        String userId = formDataListDTO.getUserId();
        String hashKey = corpid + "_" + userId;
        ExportFormDataVO exportFormDataVO  = new ExportFormDataVO();
        Workbook workbook = null;
        try {
            TransmittableThreadLocalUtil.setValue(formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), formDataListDTO.getMenuId(), formDataListDTO.getDistributorMark());

            Integer subBusinessType = formDataListDTO.getSubBusinessType();
            Integer distributorMark = formDataListDTO.getDistributorMark();
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(XbbRefTypeEnum.transferBusinessType4Distributor(businessType, distributorMark));

            long startTime = DateTimeUtil.getLong();
            LOG.warn("export_" + corpid + "_" + userId + "_" + xbbRefTypeEnum.getAlias() + "_start,time=" + DateTimeUtil.getString(startTime));


            ExcelTemplateDTO excelTemplateDTO = new ExcelTemplateDTO();


            //查看是否启用多单位公司级配置
            CompanyConfigEntity configEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.ENABLE_MULTI_UNIT.getAlias(), corpid);


            ExportStatusPojo newExportStatusPojo = new ExportStatusPojo(formDataListDTO.getAppId(), formDataListDTO.getFormId(), formDataListDTO.getMenuId(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType());
            Integer exportNum = 50000;
            //待系列一次性最多导出200条
            if (Objects.equals(subBusinessType, XbbRefTypeEnum.WAIT_INSTOCK_PURCHASE.getCode())
                    || Objects.equals(subBusinessType, XbbRefTypeEnum.WAIT_PURCHASE.getCode())
                    || Objects.equals(subBusinessType, XbbRefTypeEnum.SMART_REPLENISHMENT.getCode())
                    || Objects.equals(subBusinessType, XbbRefTypeEnum.WAIT_OUTSTOCK.getCode())) {
                formDataListDTO.setPageSize(200);
                exportNum = 200;
                newExportStatusPojo.setTotalNum(200);
            }
            // 5000条一次分页
            Integer pageSize = 5000;
            if (exportNum < pageSize) {
                pageSize = exportNum;
            }
            int num = exportNum/pageSize;
            formDataListDTO.setPageSize(pageSize);

            List<ConditionsEntityExt> copyConditionList = (List<ConditionsEntityExt>) CloneUtil.deepClone(formDataListDTO.getConditions());

            PaasFormDataEsListVO formDataListVO = new PaasFormDataEsListVO();
            formDataListDTO.setFromExport(2);
            ExcelLogPojo excelLogPojo = new ExcelLogPojo();
            StringBuilder stringBuilder = new StringBuilder();
            ExportExplainPojo exportExplainPojo = null;
            String menuName = "";
            JSONArray dataExplain = new JSONArray();
            Long dataId = 0L;
            List<FieldAttrEntityForImport> fieldAttr = new ArrayList<>();
            Integer del = formDataListDTO.getDel();

            List<ConditionsEntityExt> conditionsEntityExts;
            for (int i = 0; i < num; i++) {
                // 这边需要重置下条件，否则条件会一直累加，es语句会超长导致报错
                conditionsEntityExts = (List<ConditionsEntityExt>) CloneUtil.deepClone(copyConditionList);
                formDataListDTO.setConditions(conditionsEntityExts);
                // 这里del重置下，因为线索回收站和客户回收站在查完数据把del置成0了，所以这里需要重置下
                formDataListDTO.setDel(del);
                // 获取数据
                formDataListVO = excelDataService.getSaasDataList(formDataListDTO, formDataListDTO.getBusinessType(), subBusinessType, xbbRefTypeEnum, partialExportFlag);
                if (exportExplainPojo == null ) {
                    // 我也没办法，部分解释是通过上面的方法拿到的
                    exportExplainPojo = exportExcelExplainHelp.getExportExplain(formDataListDTO, formDataListVO);

                    PaasMenuEntity paasMenuEntity = exportExplainPojo.getPaasMenuEntity();
                    PaasFormExplainEntity paasFormExplainEntity = exportExplainPojo.getPaasFormExplainEntity();
                    fieldAttr = exportExplainPojo.getFieldAttr();


                    menuName = paasMenuEntity.getName();

                    // 处理字段解释，有一些转换是在这里面处理的
                    // 有一些subBusinessType是在getSaasDataList中变换的，比如预警查询和批次保质期查询
                    BeanUtil.copyProperties(formDataListDTO, excelTemplateDTO);
                    ExportExplainPojo dataExplainPojo = exportExcelExplainHelp.dealExplain(formDataListDTO, paasFormExplainEntity, fieldAttr, excelTemplateDTO);
                    dataExplain = dataExplainPojo.getDataExplain();
                    fieldAttr = dataExplainPojo.getFieldAttr();
                }
                if (CollectionsUtil.isEmpty(formDataListVO.getPaasFormDataESList())) {
                    break;
                }
                // 上次查询的最后一条数据，用于确认下次查询的起始位置
                if (Objects.nonNull(formDataListVO.getSortValue()) && formDataListVO.getSortValue().length>0) {
                    formDataListDTO.setSearchAfterList(formDataListVO.getSortValue());
                }
                dataId = formDataListVO.getPaasFormDataESList().get(0).getId();
                Integer size = formDataListVO.getPageHelper().getRowsCount();

                // 导入状态实体封装
                if (Objects.nonNull(size)) {
                    newExportStatusPojo.setTotalNum(size);
                }
                // 解析数据
                formatDataValue(formDataListDTO, fieldAttr, excelTemplateDTO, formDataListVO, configEntity, newExportStatusPojo);

                excelLogPojo = excelLogService.logForExportFormData(xbbRefTypeEnum, formDataListVO, formDataListDTO);

                stringBuilder.append(excelLogPojo.getLogMemo());
                workbook = excelOperatorService.createExcel(workbook, formDataListVO.getPaasFormDataESList(), dataExplain, menuName, formDataListDTO);
            }

            if (newExportStatusPojo.getTotalNum() == 0) {
                // 如果导出数据为空，则导出个空模板
                workbook =  excelOperatorService.createExcelTemplate(formDataListDTO.getBusinessType(),dataExplain, menuName, DownloadExcelTypeEnum.TEMPLATE.getType(), 0, false);
            }
            excelLogPojo.setLogMemo(stringBuilder.toString());

            excelLogService.log(newExportStatusPojo.getTotalNum(), dataId, formDataListDTO, excelLogPojo);
            long endTime = DateTimeUtil.getLong();
            LOG.warn("export_" + corpid + "_" + userId + "_" + xbbRefTypeEnum.getAlias() + "_end,time=" + DateTimeUtil.getString(endTime) + ",spendTime=" + DateTimeUtil.secondToTime((endTime - startTime) / 1000));
            String excelName = menuName + DateTimeUtil.getString(DateTimeUtil.SDFDate) + ImportConstant.EXCEL_SUFFIX;
            exportFormDataVO.setWorkbook(workbook);
            exportFormDataVO.setName(excelName);
            // OSS上传文件
            handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);
        } catch (XbbException e) {
            LOG.warn("com.xbongbong.paas.help.PaasExcelExportHelp.exportSaasFormData error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw e;
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportSaasFormData error", e);
            ExportStatusPojo errorExportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            errorExportStatusPojo.setFinish(1);
            errorExportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, errorExportStatusPojo, RedisConstant.SHORT_DURATION);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        } finally {
            closeWorkBookException(workbook);
        }
        return exportFormDataVO;
    }



    @Async(value = "exportThreadPool")
    public ExportFormDataVO exportLargeSaasFormData(FormDataListDTO formDataListDTO, Integer businessType, boolean partialExportFlag, Integer exportNum ) throws XbbException {
        String corpid = formDataListDTO.getCorpid();
        String userId = formDataListDTO.getUserId();
        String hashKey = corpid + "_" + userId;
        ExportFormDataVO exportFormDataVO  = new ExportFormDataVO();
        Workbook workbook = null;
        try {
            TransmittableThreadLocalUtil.setValue(formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType(), formDataListDTO.getMenuId(), formDataListDTO.getDistributorMark());

            Integer subBusinessType = formDataListDTO.getSubBusinessType();
            Integer distributorMark = formDataListDTO.getDistributorMark();
            XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(XbbRefTypeEnum.transferBusinessType4Distributor(businessType, distributorMark));

            long startTime = DateTimeUtil.getLong();
            LOG.warn("export_" + corpid + "_" + userId + "_" + xbbRefTypeEnum.getAlias() + "_start,time=" + DateTimeUtil.getString(startTime));

            ExcelTemplateDTO excelTemplateDTO = new ExcelTemplateDTO();
            BeanUtil.copyProperties(formDataListDTO, excelTemplateDTO);
            ExportStatusPojo newExportStatusPojo = new ExportStatusPojo(formDataListDTO.getAppId(), formDataListDTO.getFormId(), formDataListDTO.getMenuId(), formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType());

            formDataListDTO.setPageSize(exportNum);
            List<String> fieldList = formDataListDTO.getFieldList();
            // 获取id
            List<String> fieldIdList = new ArrayList<>();
            fieldIdList.add(FieldTypeEnum.DATAID.getAlias());
            formDataListDTO.setFieldList(fieldIdList);
            formDataListDTO.setFromExport(1);
            Integer del = formDataListDTO.getDel();
            PaasFormDataEsListVO formDataListVO = excelDataService.getSaasDataList(formDataListDTO, formDataListDTO.getBusinessType(), subBusinessType, xbbRefTypeEnum, partialExportFlag);

            ExportExplainPojo exportExplainPojo = exportExcelExplainHelp.getExportExplain(formDataListDTO, formDataListVO);

            PaasMenuEntity paasMenuEntity = exportExplainPojo.getPaasMenuEntity();
            PaasFormExplainEntity paasFormExplainEntity = exportExplainPojo.getPaasFormExplainEntity();
            List<FieldAttrEntityForImport> fieldAttr = exportExplainPojo.getFieldAttr();

            //查看是否启用多单位公司级配置
            CompanyConfigEntity configEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.ENABLE_MULTI_UNIT.getAlias(), corpid);

            String menuName = paasMenuEntity.getName();

            // 处理字段解释，有一些转换是在这里面处理的
            ExportExplainPojo dataExplainPojo = exportExcelExplainHelp.dealExplain(formDataListDTO, paasFormExplainEntity, fieldAttr, excelTemplateDTO);
            JSONArray dataExplain = dataExplainPojo.getDataExplain();
            fieldAttr = dataExplainPojo.getFieldAttr();
            // 总数
            int totalNum = formDataListVO.getPageHelper().getRowsCount();
            // 导入状态实体封装
            newExportStatusPojo.setTotalNum(totalNum);
            List<Long> idSet = new ArrayList<>();
            formDataListVO.getPaasFormDataESList().forEach(item->idSet.add(item.getDataId()));

            ExcelLogPojo excelLogPojo = new ExcelLogPojo();
            StringBuilder stringBuilder = new StringBuilder();

            if (CollectionsUtil.isNotEmpty(formDataListVO.getPaasFormDataESList())) {
                if (ExcelConstant.LARGE_NUM_BUSINESS.contains(businessType)) {
                    // 一次性导出数据，无需遍历
                    // 从数据库中查询
                    formatDataValue(formDataListDTO, fieldAttr, excelTemplateDTO, formDataListVO, configEntity, newExportStatusPojo);
                    excelLogPojo = excelLogService.logForExportFormData(xbbRefTypeEnum, formDataListVO, formDataListDTO);

                    stringBuilder.append(excelLogPojo.getLogMemo());

                    workbook = excelOperatorService.createExcel(formDataListVO.getPaasFormDataESList(), dataExplain, menuName, formDataListDTO);
                } else {
                    int start = 0;
                    int pageSize = 2000;
                    Integer endIndex = pageSize;
                    int num = totalNum%pageSize == 0 ?  totalNum/pageSize :  totalNum/pageSize + 1;
                    formDataListDTO.setFieldList(fieldList);
                    formDataListDTO.setFromExport(2);
                    // 对上述查询到的数据进行分页，按2000条一页
                    List<Long> searchIdSet;
                    for (int i = 0; i < num; i++) {
                        if (endIndex >= totalNum) {
                            endIndex = totalNum;
                        }
                        searchIdSet = idSet.subList(start, endIndex);
                        formDataListDTO.setDel(del);
                        List<Object> idIn = new ArrayList<>();
                        searchIdSet.forEach(item->{
                            idIn.add(item);
                        });
                        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt(FieldTypeEnum.DATAID.getAlias(), "", FieldTypeEnum.DATAID.getType(), ConditionEnum.IN.getSymbol(), idIn);
                        if (Objects.nonNull(formDataListDTO.getConditions())) {
                            boolean noHasIdIn = true;
                            for (ConditionsEntityExt item : formDataListDTO.getConditions()) {
                                if (Objects.equals(FieldTypeEnum.DATAID.getType(), item.getFieldType())) {
                                    item.setValue(idIn);
                                    noHasIdIn = false;
                                    break;
                                }
                            }
                            if (noHasIdIn) {
                                formDataListDTO.getConditions().add(conditionsEntityExt);
                            }
                        } else {
                            List<ConditionsEntityExt> list = new ArrayList<>();
                            list.add(conditionsEntityExt);
                            formDataListDTO.setConditions(list);
                        }
                        formDataListVO = excelDataService.getSaasDataList(formDataListDTO, formDataListDTO.getBusinessType(), subBusinessType, xbbRefTypeEnum, partialExportFlag);

                        formatDataValue(formDataListDTO, fieldAttr, excelTemplateDTO, formDataListVO, configEntity, newExportStatusPojo);
                        excelLogPojo = excelLogService.logForExportFormData(xbbRefTypeEnum, formDataListVO, formDataListDTO);

                        stringBuilder.append(excelLogPojo.getLogMemo());
                        start = endIndex;
                        endIndex = endIndex + pageSize;
                        workbook = excelOperatorService.createExcel(workbook, formDataListVO.getPaasFormDataESList(), dataExplain, menuName, formDataListDTO);
                    }
                }
            } else {
                workbook = excelOperatorService.createExcelTemplate(formDataListDTO.getBusinessType(), dataExplain, menuName, DownloadExcelTypeEnum.TEMPLATE.getType(), 0 , false);
            }

            long endTime = DateTimeUtil.getLong();
            LOG.warn("export_" + corpid + "_" + userId + "_" + xbbRefTypeEnum.getAlias() + "_end,time=" + DateTimeUtil.getString(endTime) + ",spendTime=" + DateTimeUtil.secondToTime((endTime - startTime) / 1000));
            String excelName = menuName + DateTimeUtil.getString(DateTimeUtil.SDFDate) + ImportConstant.EXCEL_SUFFIX;
            exportFormDataVO.setWorkbook(workbook);
            exportFormDataVO.setName(excelName);
            // OSS上传文件
            handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);

            excelLogPojo.setLogMemo(stringBuilder.toString());

            Long dataId = 0L;
            if (newExportStatusPojo.getTotalNum() == 1) {
                dataId = formDataListVO.getPaasFormDataESList().get(0).getDataId();
            }
            excelLogService.log(newExportStatusPojo.getTotalNum(), dataId, formDataListDTO, excelLogPojo);

        } catch (XbbException e) {
            LOG.warn("com.xbongbong.paas.help.PaasExcelExportHelp.exportSaasFormData error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw e;
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportSaasFormData error", e);
            ExportStatusPojo errorExportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            errorExportStatusPojo.setFinish(1);
            errorExportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, errorExportStatusPojo, RedisConstant.SHORT_DURATION);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        } finally {
            closeWorkBookException(workbook);
        }
        return exportFormDataVO;
    }




    /**
     * 数据解析
     * @param formDataListDTO
     * @param fieldAttr
     * @param excelTemplateDTO
     * @param formDataListVO
     * @param configEntity
     * @param exportStatusPojo
     * @throws XbbException
     */
    public void formatDataValue(FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttr, ExcelTemplateDTO excelTemplateDTO, PaasFormDataEsListVO formDataListVO,  CompanyConfigEntity configEntity, ExportStatusPojo exportStatusPojo ) throws XbbException {
        String hashKey = formDataListDTO.getCorpid() + "_" + formDataListDTO.getUserId();
        String corpid = formDataListDTO.getCorpid();
        Integer businessType = formDataListDTO.getBusinessType();
        List<PaasFormDataEntityExt> paasFormDataESList = formDataListVO.getPaasFormDataESList();
        if (paasFormDataESList.isEmpty()) {
            return;
        }

            Map<String, Object> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, UserEntity> userAllMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> deptMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> purchaseableGoodsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 获取员工和部门map
            getUserMapAndDeptMap(corpid, userMap, deptMap, userAllMap);

            // 获取可采购商品,目前就经销商用到
            if (Objects.equals(formDataListDTO.getBusinessType(), XbbRefTypeEnum.DISTRIBUTOR_MANAGEMENT.getCode())) {
                purchaseableGoodsMap = distributorListHelp.purchaseableGoodsList(formDataListDTO.getCorpid());
            }
            // 先用原始解释转换一遍数据
            List<FieldAttrEntity> explainList = new ArrayList<>();
            // 为了导出关联客户的客户电话
            List<String> linkCustomerAttrList = new ArrayList<>();
            // 关联数据
            List<LinkInfoPojo> linkInfoList = new ArrayList<>();
            Set<String> linkDataAttrSet = new HashSet<>();
            // 关联产品下的关联数据
            Set<String> productLinkDataAttrSet = new HashSet<>();
            Map<String, FieldAttrEntity> explainMap = formDataListVO.getExplainMap();
            explainMap.forEach((index, item) -> {
                if (Objects.equals(item.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType())
                        && Objects.equals(item.getLinkedType(), RedundantTemplateTypeEnum.CUSTOMER.getCode())) {
                    linkCustomerAttrList.add(item.getAttr());
                }
                if (ExplainUtil.isSubForm(item.getFieldType())) {
                    List<? extends FieldAttrEntity> jsonArray = item.getSubForm().getItems();
                    boolean isRelativeProduct =  Objects.equals(item.getFieldType(), FieldTypeEnum.SELECT_PRODUCT.getType()) && Objects.equals(0, item.getIsRedundant());
                    for (int i = 0; i < jsonArray.size(); i++) {
                        FieldAttrEntity subForm = jsonArray.get(i);
                        if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), subForm.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), subForm.getFieldType())) {
                            linkInfoList.add(subForm.getLinkInfo());
                            linkDataAttrSet.add(item.getAttr() + StringConstant.POINT + subForm.getAttr());
                            if (isRelativeProduct) {
                                productLinkDataAttrSet.add(item.getAttr() + StringConstant.POINT + subForm.getAttr());
                            }
                        }
                    }
                } else if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), item.getFieldType())) {
                    linkInfoList.add(item.getLinkInfo());
                    linkDataAttrSet.add(item.getAttr());
                }
                explainList.add(item);
            });
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO);

        List<Long> formIdList = new ArrayList<>();
        List<Long> workOrderFormIdList = new ArrayList<>();
        for (LinkInfoPojo linkInfoPojo : linkInfoList) {
            if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                workOrderFormIdList.add(linkInfoPojo.getLinkFormId());
            } else {
                formIdList.add(linkInfoPojo.getLinkFormId());
            }
        }
        // 非工单解释
        Map<String, PaasFormExplainEntity> formExplainMap = baseFormDataLinkDataHelp.getExplainMapByFormIdList(formIdList, corpid);
        // 工单解释
        Map<String, WorkOrderExplainEntity> workOrderFormExplainMap = baseFormDataLinkDataHelp.getWorkOrderExplainMapByFormId(workOrderFormIdList, corpid);
        LinkResultDataDTO linkResultDataDTO = new LinkResultDataDTO();
        BeanUtil.copyProperties(formDataListDTO, linkResultDataDTO);
        int size = paasFormDataESList.size();

        Map<String, Object> linkDataIdMap;
        for (int k = 0; k < size; k += ExcelConstant.PER_WRITE_INSERT_BATCH_COUNT) {
            Set<Object> linkDataIdSet = new HashSet<>();
            linkDataIdMap = new HashMap<>(ExcelConstant.PER_WRITE_INSERT_BATCH_COUNT);
            int toIndex = k + ExcelConstant.PER_WRITE_INSERT_BATCH_COUNT;
            if (toIndex > size) {
                toIndex = size;
            }
            List<PaasFormDataEntityExt> formDataEntityExts = paasFormDataESList.subList(k, toIndex);
            // 经销商账号text_4不存值，这里塞回，导出用
            if (Objects.equals(XbbRefTypeEnum.DISTRIBUTOR_ACCOUNT.getCode(), businessType)) {
                distributorAccountService.setDistributorName(formDataEntityExts, corpid);
            }
            List<Long> dataIdList = new ArrayList<>();
            Set<Long> customerIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Long linkCustomerId;
            Set<String> linkDataSet = new HashSet<>();
            Map<String, Set<String>> subFormLinkDataMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 解析子表单中的关联数据字段
            FormDataListAnalysisDataHelp.getLinkDataField(linkDataAttrSet, FieldAttrConstant.SUB_FORM, linkDataSet, subFormLinkDataMap);
            for (PaasFormDataEntityExt paasFormDataEntityExt : formDataEntityExts) {
                for (String attr : linkCustomerAttrList) {
                    try {
                        linkCustomerId = FastJsonHelper.getLongOrDefaultFromFormData(paasFormDataEntityExt.getData(), attr, 0L);
                    } catch (XbbException e) {
                        linkCustomerId = 0L;
                    }
                    customerIdSet.add(linkCustomerId);
                }
                dataIdList.add(paasFormDataEntityExt.getDataId());

                // 这个好难啊
                FormDataListAnalysisDataHelp.getLinkDataSet(paasFormDataEntityExt.getData(), subFormLinkDataMap, linkDataSet, linkDataIdSet, linkDataAttrSet, linkDataIdMap);
            }
            customerIdSet.remove(0L);
            // 获取关联数据字段所需要的数据
            LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
            linkResultDataVO.setExplainMap(explainMap);
            linkResultDataVO.setLinkDataSet(linkDataIdSet);
            linkResultDataVO.setLinkData(linkDataIdMap);
            linkResultDataVO.setExplainList(explainList);
            Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkData4Field(linkResultDataDTO, linkResultDataVO);

            //多单位单位解释
            List<ItemPoJo> productItems = relativeProductHelp.getBusinessUnitItems(corpid);

            Map<Long, String> phoneMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (CollectionsUtil.isNotEmpty(customerIdSet)) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, customerIdSet));
                List<String> fieldList = new ArrayList<>();
                fieldList.add("data." + CustomerManagementEnum.PHONE.getAttr() + StringConstant.POINT + StringConstant.PHONE_TEL_ATTR);
                fieldList.add(FieldTypeEnum.DATAID.getAlias());
                fieldList.add(StringConstant.FORM_ID);
                IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());

                List<PaasFormDataEntityExt> customerList = esHelper.findByScroll(indexTypeEnum, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                // 号码可见性处理
                Map<Long, Map<String, FieldAttrEntity>> customerFormIdAndExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Set<Long> customerFormIds = new HashSet<>();
                for (PaasFormDataEntityExt customer : customerList) {
                    customerFormIds.add(customer.getFormId());
                }
                Map<String, Object> param = new HashMap<>();
                param.put("corpid", corpid);
                param.put("formIdIn", customerFormIds);
                List<PaasFormExplainEntity> explainEntities = paasFormExplainModel.findEntitys(param);
                for (PaasFormExplainEntity explainEntity : explainEntities) {
                    customerFormIdAndExplainMap.put(explainEntity.getFormId(), ExplainUtil.getExplainMap(explainEntity.getExplains(), null));
                }

                String phone;
                HandlerExplainDTO customerHandlerExplainDTO = new HandlerExplainDTO();
                BeanUtil.copyProperties(formDataListDTO, customerHandlerExplainDTO);
                for (PaasFormDataEntityExt paasFormDataEntityExt : customerList) {
                    Map<String, FieldAttrEntity> customerExplainMap = customerFormIdAndExplainMap.get(paasFormDataEntityExt.getFormId());
                    customerHandlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
                    boolean attrVisible = commonHelp.attrCanSee(CustomerManagementEnum.PHONE.getAttr(), customerExplainMap, customerHandlerExplainDTO);
                    boolean isShow = false;
                    if(attrVisible){
                        List<? extends FieldAttrEntity> explainSubFormList = customerExplainMap.get(CustomerManagementEnum.PHONE.getAttr()).getSubForm().getItems();
                        Map<String, FieldAttrEntity> explainSubFormMap = new HashMap<>(explainSubFormList.size());
                        explainSubFormList.forEach((item) -> explainSubFormMap.put(item.getAttr(), item));
                        boolean text2CanSee = commonHelp.attrCanSee(StringConstant.PHONE_TEL_ATTR, explainSubFormMap, customerHandlerExplainDTO);
                        if(text2CanSee){
                            isShow = true;
                        }
                    }
                    phone = "";
                    JSONObject data = paasFormDataEntityExt.getData();
                    if (Objects.nonNull(data)) {
                        JSONArray phoneArr = data.getJSONArray(CustomerManagementEnum.PHONE.getAttr());
                        if (phoneArr != null && !phoneArr.isEmpty()) {
                            for (int i = 0; i < phoneArr.size(); i ++) {
                                JSONObject phoneObj = phoneArr.getJSONObject(i);
                                String tel = phoneObj.getString(StringConstant.PHONE_TEL_ATTR);
                                if (!isShow && StringUtil.isNotEmpty(tel)) {
                                    if (tel.length() > 5) {
                                        phone = tel.substring(0, 3) + "****" + tel.substring(tel.length() - 2, tel.length());
                                    } else {
                                        phone = "*****";
                                    }
                                } else if (isShow && StringUtil.isNotEmpty(tel)) {
                                    phone = phoneObj.getString(StringConstant.PHONE_TEL_ATTR);
                                }
                                break;
                            }
                        }
                    }
                    phoneMap.put(paasFormDataEntityExt.getDataId(), phone);
                }
            }
            Map<Long, List<UserAndDepTeamEntity>> teamMap = getVisibleRangeUserTeam(corpid, businessType, dataIdList);
            Map<Long, List<UserAndDepTeamEntity>> competitorUserTeam = getCompetitorUserTeam(corpid, businessType, dataIdList);
            // 前置处理负责人和协同人
            Map<Long, Set<String>> mainUserMap = new HashMap<>();
            Map<Long, Set<String>> coUserMap = new HashMap<>();
            boolean isPublic = Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode()) || Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.CLUE_PUBLIC.getCode());
            getMainAndCoUserMapForExport(corpid, businessType, excelTemplateDTO.getSaasMark(), dataIdList, mainUserMap, coUserMap, isPublic);

                if(Objects.nonNull(configEntity) && Objects.equals(BasicConstant.ONE.toString(), configEntity.getConfigValue())){
                    if (StockConstant.EXPORT_MULTI_UNIT_TYPE_LIST.contains(businessType)) {
                        for (FieldAttrEntity fieldAttrEntity : explainList) {
                            Integer fieldType = fieldAttrEntity.getFieldType();
                            if (Objects.equals(FieldTypeEnum.SELECT_PRODUCT.getType(), fieldType)){
                                List<FieldAttrEntity> items = (List<FieldAttrEntity>) fieldAttrEntity.getSubForm().getItems();
                                importHelper.exportAddExplain(items, productItems);
                            }
                        }
                    }else if (StockConstant.IMPORT_MULTI_UNIT_TYPE.contains(businessType)){
                        for (FieldAttrEntity fieldAttrEntity : explainList) {
                            Integer fieldType = fieldAttrEntity.getFieldType();
                            if (Objects.equals(FieldTypeEnum.SELECT_PRODUCT.getType(), fieldType)){
                                List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                                for (FieldAttrEntity subFieldAttrEntity : subExplainList) {
                                    if (Objects.equals(subFieldAttrEntity.getAttr(), SelectProductEnum.UNIT.getAttr())) {
                                        subFieldAttrEntity.setItems(productItems);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                int j = 0;
                ExportLinkDataPojo exportLinkDataPojo = new ExportLinkDataPojo(formExplainMap, workOrderFormExplainMap, formDataMap);
                Map<Long, PublicGroupSeniorEntity> publicGroupMap = publicGroupSeniorService.getPublicGroupMap(formDataListDTO.getFormId(), formDataListDTO.getCorpid());
                // 获取 模板字段map
            OnlineEditorMap4ExportPojo onlineEditorMap4ExportPojo = onlineEditorHelp.getOnlineEditorMap4Export(corpid, formDataEntityExts, explainList);

            if (!Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.WAIT_OUTSTOCK.getCode())) {
                    for (PaasFormDataEntityExt paasFormDataEntityExt : formDataEntityExts) {
                        handleVisibleUserTeam(teamMap, businessType, paasFormDataEntityExt);
                        handleCompetitorUserTeam(competitorUserTeam,businessType,paasFormDataEntityExt);
                        // 设置协同人和负责人
                        setMainAndCoUserForExport(excelTemplateDTO.getSaasMark(), businessType, userAllMap, mainUserMap, coUserMap, paasFormDataEntityExt);

    //                userHelp.setOwnerAndCoUser(paasFormDataEntityExt.getData(), paasFormDataEntityExt, excelTemplateDTO.getSaasMark(), businessType, userAllMap);
                        // 为了兼容产品新增负责人字段
                        if (Objects.equals(businessType, XbbRefTypeEnum.PRODUCT.getCode())) {
                            paasFormDataEntityExt.getData().put(FieldTypeEnum.OWNERID.getAlias(), Arrays.asList(paasFormDataEntityExt.getOwnerId()));
                        }
                        JSONObject formDataObj = paasFormDataEntityExt.getData();
                        handlerExplainDTO.setOwnerId(JSON.parseArray(JSON.toJSONString(formDataObj.get(FieldTypeEnum.OWNERID.getAlias())), String.class));
                        handlerExplainDTO.setCoUserId(JSON.parseArray(JSON.toJSONString(formDataObj.get(FieldTypeEnum.COUSERID.getAlias())), String.class));
                        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());

                        if(!Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.WAIT_INSTOCK_PURCHASE.getCode())
                                && !Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.WAIT_PURCHASE.getCode())
                                && !Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.WAIT_OUTSTOCK.getCode())
                                && !Objects.equals(formDataListDTO.getSubBusinessType(),XbbRefTypeEnum.SMART_REPLENISHMENT.getCode())
                        ){
                            importHelper.formatCommonData4Export(userMap, deptMap, paasFormDataEntityExt, formDataObj, explainList, phoneMap, exportLinkDataPojo, businessType, purchaseableGoodsMap);
                        }
                        if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.CUSTOMER_PUBLIC.getCode()) || Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.CLUE_PUBLIC.getCode())) {
                            formDataObj.put("preOwnerId", formDataObj.get(FieldTypeEnum.OWNERID.getAlias()));
                            formDataObj.remove(FieldTypeEnum.OWNERID.getAlias());
                            formDataObj.remove(FieldTypeEnum.COUSERID.getAlias());
                        }
                        onlineEditorHelp.packageData4Export( onlineEditorMap4ExportPojo,  formDataObj);
                        // 所有下拉框全部从改造的解释中取  阶段推进器的值需要特殊处理解释
                        importHelper.formatDropDown4Export(fieldAttr, formDataObj, formDataListDTO);
                        //处理所属分组
                        if (Objects.equals(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), businessType) || Objects.equals(XbbRefTypeEnum.CLUE.getCode(), businessType)) {
                            //公海分组字段渲染
                            String publicGroup = Objects.isNull(explainMap.containsKey(CustomerManagementEnum.PUBLIC_GROUP.getAttr())) ? null : CustomerManagementEnum.PUBLIC_GROUP.getAttr();
                            if (Objects.equals(XbbRefTypeEnum.CLUE.getCode(), businessType)) {
                                publicGroup = Objects.isNull(explainMap.containsKey(ClueEnum.PUBLIC_GROUP.getAttr())) ? null : ClueEnum.PUBLIC_GROUP.getAttr();
                            }
                            publicGroupSeniorService.dealId2GroupName(publicGroup,formDataObj, publicGroupMap);
                        }
                        // 字段可见性判断
                        for (FieldAttrEntity fieldAttrEntity : explainList) {
                            if (ExplainUtil.isFieldNeedHide(fieldAttrEntity, handlerExplainDTO)){
                                formDataObj.put(fieldAttrEntity.getAttr(), "");
                            } else if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())) {
                                // 子表单也有高级权限
                                List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                                for (FieldAttrEntity subFieldAttrEntity : subExplainList) {
                                    if (ExplainUtil.isFieldNeedHide(subFieldAttrEntity, handlerExplainDTO)){
                                        try {
                                            JSONArray jsonArray  = formDataObj.getJSONArray(fieldAttrEntity.getAttr());
                                            for (int i = 0; i < jsonArray.size(); i++) {
                                                JSONObject jsonObject = jsonArray.getJSONObject(i);
                                                jsonObject.put(subFieldAttrEntity.getAttr(), "");
                                            }
                                        } catch (Exception e) {
                                            LOG.error("export invisible subForm error ", e);
                                        }
                                    }
                                }
                            }
                        }

                        int successNum = exportStatusPojo.getSuccessNum();
                        exportStatusPojo.setSuccessNum(++successNum);

                        // 每隔50组/数据导完时，刷新一次当前导入状态
                        if (j == 0 || j % 50 == 0) {
                            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
                        }
                        j++;
                    }
                } else if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.WAIT_OUTSTOCK.getCode())) {
                    //导出的格式需要转换
                    for (PaasFormDataEntityExt formDataEntityExt : formDataEntityExts) {
                        JSONObject data = formDataEntityExt.getData();
                        data.put(WaitOutstockEnum.STATUS.getAttr(), ItemUtil.parseItemPoJoFromFormData2String(data, WaitOutstockEnum.STATUS.getAttr(), ""));
                        data.put(WaitOutstockEnum.UNIT.getAttr(), ItemUtil.parseItemPoJoFromFormData2String(data, WaitOutstockEnum.UNIT.getAttr(), ""));
                    }
                }
            }
            // 最后更新一次最终状态
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.COMMON_DURATION);

        formDataListDTO.setUserAllMap(userAllMap);
        formDataListDTO.setUserMap(userMap);
        formDataListDTO.setDeptMap(deptMap);

        // 电话掩码
        UserVO loginUser = formDataListDTO.getLoginUser();
        for (FieldAttrEntity field : fieldAttr) {
            // 处理系统电话字段
            if (ExplainUtil.isSystemPhoneField(field) && Objects.nonNull(loginUser) && !loginUser.isAdminOrBoss()) {
                FieldAttrEntity phoneField = field.getSubForm().getItems().stream().filter(item -> Objects.equals(item.getAttr(), "text_2")).findFirst().orElse(null);
                // 开启了电话掩码功能才需要处理
                if (Objects.nonNull(phoneField) && Objects.equals(phoneField.getIsMaskTelephone(), BasicConstant.ONE)) {
                    for (PaasFormDataEntityExt formDataEntity : paasFormDataESList) {
                        JSONObject formData = formDataEntity.getData();
                        formDataAnalysisHelp.analysisTelephoneNumber4Export(field, phoneField, formData, loginUser);
                    }
                }
            }
        }

        handleImportService.formatExportValue(paasFormDataESList, formDataListDTO, fieldAttr);
        if (RelativeProductImportEnum.exportProductBusinessTypeList().contains(businessType)) {
            Set<Object> linkDataIdSet = new HashSet<>();
            // 这个好难啊
            Map<String, Object> productLinkDataIdMap = new HashMap<>();
            Map<String, Set<String>> subFormLinkDataMap = new HashMap<>();
            if (CollectionsUtil.isNotEmpty(productLinkDataAttrSet)) {
                // 解析关联产品下的关联数据字段
                FormDataListAnalysisDataHelp.getLinkDataField(linkDataAttrSet, productLinkDataAttrSet, subFormLinkDataMap);
                for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
                    FormDataListAnalysisDataHelp.getLinkDataSet(paasFormDataEntityExt.getData(), subFormLinkDataMap, new HashSet<>(), linkDataIdSet, productLinkDataAttrSet, productLinkDataIdMap);
                }
            }
            // 获取关联数据字段所需要的数据
            LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
            linkResultDataVO.setExplainMap(explainMap);
            linkResultDataVO.setLinkDataSet(linkDataIdSet);
            linkResultDataVO.setLinkData(productLinkDataIdMap);
            linkResultDataVO.setExplainList(explainList);
            Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkData4Field(linkResultDataDTO, linkResultDataVO);
            ExportLinkDataPojo exportLinkDataPojo = new ExportLinkDataPojo(formExplainMap, workOrderFormExplainMap, formDataMap);
            for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
                for (FieldAttrEntity fieldAttrEntity : explainList) {
                    if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SELECT_PRODUCT.getType()) && Objects.equals(fieldAttrEntity.getIsOpen(), 1)) {
                        // 子表单也有高级权限
                        List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                        proFormHelp.setProductAccuracy(fieldAttrEntity, corpid, formDataListDTO.getUserId());
                        JSONArray jsonArray = paasFormDataEntityExt.getData().getJSONArray(fieldAttrEntity.getAttr()) == null ? new JSONArray() : paasFormDataEntityExt.getData().getJSONArray(fieldAttrEntity.getAttr());
                        for (FieldAttrEntity subFieldAttrEntity : subExplainList) {
                            if (Objects.equals(subFieldAttrEntity.getIsRedundant(), 1)) {
                                try {
                                    // 产品子表单内自定义字段解析
                                    for (int i = 0; i < jsonArray.size(); i++) {
                                        if (!(jsonArray.get(i) instanceof JSONObject)){
                                            continue;
                                        }
                                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                                        importHelper.formatRelativeProductData4Export(userMap, deptMap, jsonObject, subFieldAttrEntity, exportLinkDataPojo, corpid);
                                    }
                                } catch (Exception e) {
                                    LOG.error("export customer field error ", e);
                                }
                            } else {
                                if (Objects.equals(subFieldAttrEntity.getFieldType(), FieldTypeEnum.NUM.getType())) {
                                    try {
                                        for (int i = 0; i < jsonArray.size(); i++) {
                                            if (!(jsonArray.get(i) instanceof JSONObject)){
                                                continue;
                                            }
                                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                                            if (Objects.nonNull(jsonObject.getDouble(subFieldAttrEntity.getAttr())) && Objects.equals(subFieldAttrEntity.getIntegerOnly(), 0)){
                                                jsonObject.put(subFieldAttrEntity.getAttr(), attrDecimalPrecisionHelper.setDecPrecision(jsonObject.getDouble(subFieldAttrEntity.getAttr()), subFieldAttrEntity.getAccuracy()));
                                            }
                                        }
                                    } catch (Exception e) {
                                        LOG.error(JSON.toJSONString(jsonArray));
                                        LOG.error("export num select product error ", e);
                                    }
                                } else if (Objects.equals(ProductEnum.UNIT.getAttr(),  subFieldAttrEntity.getAttr()) || Objects.equals(SelectProductEnum.BASIC_UNIT.getAttr(),  subFieldAttrEntity.getAttr())){
                                    for (int i = 0; i < jsonArray.size(); i++) {
                                        if (!(jsonArray.get(i) instanceof JSONObject)){
                                            continue;
                                        }
                                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                                        Object itemValue = ItemUtil.getCustomItemList(subFieldAttrEntity, jsonObject);
                                        jsonObject.put(subFieldAttrEntity.getAttr(), itemValue);
                                        jsonObject.remove(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
                                    }
                                }
                            }
                            if (ExplainUtil.isFieldNeedHide(subFieldAttrEntity, handlerExplainDTO)) {
                                try {
                                    for (int i = 0; i < jsonArray.size(); i++) {
                                        if (!(jsonArray.get(i) instanceof JSONObject)){
                                            continue;
                                        }
                                        JSONObject jsonObject = jsonArray.getJSONObject(i);
                                        jsonObject.put(subFieldAttrEntity.getAttr(), "");
                                    }
                                } catch (Exception e) {
                                    LOG.error("export invisible select error ", e);
                                }
                            }
                        }
                    }/* else if ((Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.UPLOAD.getType()) || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.IMAGE.getType())) && Objects.equals(fieldAttrEntity.getIsOpen(), 1)) {
                        JSONArray fileArray = JSONObject.parseArray(paasFormDataEntityExt.getData().getString(fieldAttrEntity.getAttr()));
                        if (Objects.nonNull(fileArray)) {
                            StringBuilder exortFile = new StringBuilder();
                            for (int i = 1; i <= fileArray.size(); i++) {
                                if (i != 1) {
                                    exortFile.append('\n');
                                }
                                if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.IMAGE.getType())) {
                                    exortFile.append(i).append(".").append('\n').append("(").append(fileArray.getString(i-1)).append(")");
                                } else {
                                    JSONObject fileJson = fileArray.getJSONObject(i - 1);
                                    exortFile.append(i).append(".").append(fileJson.getString("filename")).append('\n').append("(").append(fileJson.getString("attachIndex")).append(")");
                                }
                            }
                            paasFormDataEntityExt.getData().put(fieldAttrEntity.getAttr(), exortFile);
                        }
                    } else if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType()) && Objects.equals(fieldAttrEntity.getIsOpen(), 1)) {
                        analysisSubFormFile(fieldAttrEntity, paasFormDataEntityExt);
                    }*/
                }
            }
        } else {
            for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
                for (FieldAttrEntity fieldAttrEntity : explainList) {
                    // 下面注释的内容为图片与文件解析，已经在其他地方解析过
                    /*if (Objects.nonNull(formDataListDTO.getExcelPartialExportPojo()) && Objects.equals(formDataListDTO.getExcelPartialExportPojo().getPartialExport(), 1)
                            && (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.UPLOAD.getType()) || Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.IMAGE.getType())) && Objects.equals(fieldAttrEntity.getIsOpen(), 1)) {
                        JSONArray fileArray = JSONObject.parseArray(paasFormDataEntityExt.getData().getString(fieldAttrEntity.getAttr()));
                        if (Objects.nonNull(fileArray)) {
                            StringBuilder exortFile = new StringBuilder();
                            for (int i = 1; i <= fileArray.size(); i++) {
                                if (i != 1) {
                                    exortFile.append('\n');
                                }
                                if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.IMAGE.getType())) {
                                    exortFile.append(i).append(".").append('\n').append("(").append(fileArray.getString(i - 1)).append(")");
                                } else {
                                    JSONObject fileJson = fileArray.getJSONObject(i - 1);
                                    exortFile.append(i).append(".").append(fileJson.getString("filename")).append('\n').append("(").append(fileJson.getString("attachIndex")).append(")");
                                }
                            }
                            paasFormDataEntityExt.getData().put(fieldAttrEntity.getAttr(), exortFile);
                        }
                    } else
                    if (Objects.nonNull(formDataListDTO.getExcelPartialExportPojo()) && Objects.equals(formDataListDTO.getExcelPartialExportPojo().getPartialExport(), 1)
                            && Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType()) && Objects.equals(fieldAttrEntity.getIsOpen(), 1)) {
                        analysisSubFormFile(fieldAttrEntity, paasFormDataEntityExt);
                    }*/
                }
            }
        }
    }


    @Async(value = "exportThreadPool")
    public ExportFormDataVO exportWorkOrderList(FormDataListDTO formDataListDTO, SpecialWorkOrderExportDTO specialWorkOrderExportDTO) throws XbbException {
        String[] split = formDataListDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        ExportFormDataVO exportFormDataVO = new ExportFormDataVO();
        String hashKey = formDataListDTO.getCorpid() + "_" + formDataListDTO.getUserId();
        Workbook workbook = null;
        try {
            String corpid = formDataListDTO.getCorpid();
            Integer businessType = formDataListDTO.getBusinessType();
            ExcelTemplateDTO excelTemplateDTO = new ExcelTemplateDTO();
            BeanUtil.copyProperties(formDataListDTO, excelTemplateDTO);
            Map<String, Object> explainParam = BeanUtil.convertBean2Map(excelTemplateDTO, true);
            List<WorkOrderExplainEntity> formExplainList = workOrderExplainModel.list(explainParam);
            if (formExplainList == null || formExplainList.isEmpty()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            WorkOrderExplainEntity workOrderExplainEntity = formExplainList.get(0);
            Long menuId = Objects.isNull(formDataListDTO.getMenuId()) ? workOrderExplainEntity.getMenuId() : formDataListDTO.getMenuId();
            PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(menuId, corpid);
            if (paasMenuEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_NOT_EXIST);
            }
            String menuName = paasMenuEntity.getName();
            Boolean isJxcUse = paasAppService.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);
            List<FieldAttrEntityForImport> fieldAttrList = JSON.parseArray(workOrderExplainEntity.getExplains(), FieldAttrEntityForImport.class);
            //过滤阶段ID以及拥有者,出库完全标志也过滤，不知道哪个皮皮虾加进来了，导致测试环境上有
            Iterator<FieldAttrEntityForImport> iterator = fieldAttrList.iterator();
            while (iterator.hasNext()) {
                FieldAttrEntityForImport fieldAttrEntityForImport = iterator.next();
                if (Objects.equals(fieldAttrEntityForImport.getAttr(), WorkOrderEnum.STAGE.getAttr())) {
                    iterator.remove();
                }
                if (Objects.equals(fieldAttrEntityForImport.getAttr(), WorkOrderEnum.ALL_OUTBOUND.getAttr())) {
                    iterator.remove();
                }
                if (Objects.equals(fieldAttrEntityForImport.getAttr(), WorkOrderEnum.SPARE_PARTS.getAttr()) && !isJxcUse) {
                    SubFormPoJo subForm = fieldAttrEntityForImport.getSubForm();
                    List<FieldAttrEntity> fieldAttrEntityList = (List<FieldAttrEntity>) subForm.getItems();
                    fieldAttrEntityList.removeIf(field -> (Objects.equals(field.getAttr(), WorkOrderProductEnum.OUTSTOCK_NUM.getAttr()) || Objects.equals(field.getAttr(), WorkOrderProductEnum.WAIT_OUTSTOCK_NUM.getAttr())));
                    subForm.setItems(fieldAttrEntityList);
                }
            }
            // 处理关联新建表单
            if (Objects.equals(formDataListDTO.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
                LinkFormImportPojo linkFormImportPojo = new LinkFormImportPojo();
                BeanUtil.copyProperties(formDataListDTO, linkFormImportPojo);
                linkFormImportPojo.setFieldAttrEntityForImportList(fieldAttrList);
                linkFormImportPojo.setFormImportOrExport(ImportConstant.FROM_EXPORT);
                handleImportService.handleLinkForm(linkFormImportPojo, DistributorMarkEnum.OTHER.getCode());
            }
            boolean excelPartialFlag = null != formDataListDTO.getExcelPartialExportPojo()
                    && CollectionsUtil.isNotEmpty(formDataListDTO.getExcelPartialExportPojo().getPartialSelectAttrs());
            // 过滤不需要导入的字段
            handleImportService.filterUnExportFields(formDataListDTO.getCorpid(), fieldAttrList, formDataListDTO.getSaasMark(), ImportConstant.FROM_EXPORT, formDataListDTO.getBusinessType(), excelPartialFlag);
            // 处理公有的需要转换的字段
            handleImportService.handleCommonNeedTransferFields(fieldAttrList, formDataListDTO);
            JSONArray dataExplain;

            // SaaS字段解释特处理
            excelTemplateDTO.setFormImportOrExport(ImportConstant.FROM_EXPORT);
            dataExplain = handleImportService.handleSpecialExplain(fieldAttrList, excelTemplateDTO);

            //部分导出需要过滤一些没有被选择的字段start
            if(excelPartialFlag){
                List<String> partialSelectAttrs = formDataListDTO.getExcelPartialExportPojo().getPartialSelectAttrs();
                fieldAttrList.removeIf(entry -> !partialSelectAttrs.contains(entry.getAttr()));
                dataExplain = JSON.parseArray(JSON.toJSONString(fieldAttrList));
            }
            //部分导出需要过滤一些没有被选择的字段end

            Map<String, Object> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, UserEntity> userAllMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> deptMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

            // 获取员工和部门map
            getUserMapAndDeptMap(corpid, userMap, deptMap, userAllMap);
            List<WorkOrderEntityExt> workOrderEntityExtList = specialWorkOrderExportDTO.getPaasFormDataESList();
            if (workOrderEntityExtList.isEmpty()) {
                throw new XbbException(ImportErrorCodeEnum.API_ERROR_235005);
            }
            // 先用原始解释转换一遍数据
            List<FieldAttrEntity> explainList = new ArrayList<>();
            // 为了导出关联客户的客户电话
            List<String> linkCustomerAttrList = new ArrayList<>();
            // 关联数据
            List<LinkInfoPojo> linkInfoList = new ArrayList<>();
            Set<String> linkDataAttrSet = new HashSet<>();
            // 关联产品下的关联数据
            Set<String> productLinkDataAttrSet = new HashSet<>();
            Map<String, FieldAttrEntity> explainMap = specialWorkOrderExportDTO.getExplainMap();
            explainMap.forEach((index, item) -> {
                if (Objects.equals(item.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()) && Objects.equals(item.getLinkedType(), RedundantTemplateTypeEnum.CUSTOMER.getCode())) {
                    linkCustomerAttrList.add(item.getAttr());
                }
                if (ExplainUtil.isSubForm(item.getFieldType())) {
                    List<? extends FieldAttrEntity> jsonArray = item.getSubForm().getItems();
                    boolean isRelativeProduct = Objects.equals(item.getFieldType(), FieldTypeEnum.SELECT_PRODUCT.getType());
                    for (int i = 0; i < jsonArray.size(); i++) {
                        FieldAttrEntity subForm = jsonArray.get(i);
                        if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), subForm.getFieldType())) {
                            linkInfoList.add(subForm.getLinkInfo());
                            linkDataAttrSet.add(item.getAttr() + StringConstant.POINT + subForm.getAttr());
                            if (isRelativeProduct) {
                                productLinkDataAttrSet.add(item.getAttr() + StringConstant.POINT + subForm.getAttr());
                            }
                        }
                    }
                } else if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), item.getFieldType())) {
                    linkInfoList.add(item.getLinkInfo());
                    linkDataAttrSet.add(item.getAttr());
                }
                explainList.add(item);
            });
            //查看是否启用多单位公司级配置
            CompanyConfigEntity configEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.ENABLE_MULTI_UNIT.getAlias(), corpid);
            //导出涉及多单位业务拼接解释
            List<ItemPoJo> productItems = relativeProductHelp.getBusinessUnitItems(corpid);
            if(Objects.nonNull(configEntity) && Objects.equals(BasicConstant.ONE, Integer.valueOf(configEntity.getConfigValue()))){
                for (FieldAttrEntity fieldAttrEntity : explainList) {
                    Integer fieldType = fieldAttrEntity.getFieldType();
                    if (Objects.equals(FieldTypeEnum.SELECT_PRODUCT.getType(), fieldType)){
                        List<FieldAttrEntity> items = (List<FieldAttrEntity>) fieldAttrEntity.getSubForm().getItems();
                        importHelper.exportAddExplain(items, productItems);
                    }
                }
            }
            HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
            BeanUtil.copyProperties(formDataListDTO, handlerExplainDTO);

            List<Long> formIdList = new ArrayList<>();
            List<Long> workOrderFormIdList = new ArrayList<>();
            for (LinkInfoPojo linkInfoPojo : linkInfoList) {
                if (Objects.equals(linkInfoPojo.getLinkBusinessType(), XbbRefTypeEnum.WORK_ORDER.getCode())) {
                    workOrderFormIdList.add(linkInfoPojo.getLinkFormId());
                } else {
                    formIdList.add(linkInfoPojo.getLinkFormId());
                }
            }

            // 非工单解释
            Map<String, PaasFormExplainEntity> formExplainMap = baseFormDataLinkDataHelp.getExplainMapByFormIdList(formIdList, corpid);
            // 工单解释
            Map<String, WorkOrderExplainEntity> workOrderFormExplainMap = baseFormDataLinkDataHelp.getWorkOrderExplainMapByFormId(workOrderFormIdList, corpid);
            LinkResultDataDTO linkResultDataDTO = new LinkResultDataDTO();
            BeanUtil.copyProperties(formDataListDTO, linkResultDataDTO);
            int size = workOrderEntityExtList.size();
            ExportStatusPojo exportStatusPojo = new ExportStatusPojo();
            BeanUtil.copyProperties(formDataListDTO, exportStatusPojo);
            exportStatusPojo.setTotalNum(size);

            for (int i = 0; i < size; i += ExcelConstant.PER_WRITE_INSERT_BATCH_COUNT) {
                Set<Object> linkDataIdSet = new HashSet<>();
                int toIndex = i + ExcelConstant.PER_WRITE_INSERT_BATCH_COUNT;
                if (toIndex > size) {
                    toIndex = size;
                }
                List<WorkOrderEntityExt> workOrderEntityExts = workOrderEntityExtList.subList(i, toIndex);
                List<Long> dataIdList = new ArrayList<>();
                Set<Long> customerIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Long linkCustomerId = 0L;
                for (WorkOrderEntityExt workOrderEntityExt : workOrderEntityExts) {
                    for (String attr : linkCustomerAttrList) {
                        try {
                            linkCustomerId = FastJsonHelper.getLongOrDefaultFromFormData(workOrderEntityExt.getData(), attr, 0L);
                        } catch (Exception e) {
                            linkCustomerId = 0L;
                        }
                        customerIdSet.add(linkCustomerId);
                    }
                    dataIdList.add(workOrderEntityExt.getId());

                    // 这个好难啊
                    if (CollectionsUtil.isNotEmpty(linkDataAttrSet)) {
                        JSONObject data = workOrderEntityExt.getData();
                        linkDataAttrSet.forEach(item->{
                            if (item.contains(FieldAttrConstant.SUB_FORM)) {
                                String[] attrArray = item.split("\\.");
                                String attr = attrArray[0];
                                JSONArray jsonArray = data.getJSONArray(attr);
                                if (CollectionsUtil.isNotEmpty(jsonArray)) {
                                    for (int a = 0; a < jsonArray.size(); a++) {
                                        JSONObject jsonObject = jsonArray.getJSONObject(a);
                                        if (jsonObject.getLong(attrArray[1]) instanceof Number && !Objects.equals(jsonObject.getLong(attrArray[1]), 0L)) {
                                            Long id = jsonObject.getLong(attrArray[1]);
                                            if (Objects.nonNull(id)) {
                                                linkDataIdSet.add(id);
                                            }
                                        }
                                    }
                                }
                            } else if (data.get(item) instanceof Number && !Objects.equals(data.getLong(item), 0L)) {
                                Long id = data.getLong(item);
                                if (Objects.nonNull(id)) {
                                    linkDataIdSet.add(id);
                                }
                            }
                        });
                    }
                }
                customerIdSet.remove(0L);

                // 获取关联数据字段所需要的数据
                LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
                linkResultDataVO.setExplainMap(explainMap);
                linkResultDataVO.setLinkDataSet(linkDataIdSet);
                linkResultDataVO.setExplainList(explainList);
                Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkDataOfBusinessType(linkResultDataDTO, linkResultDataVO);

                Map<Long, String> phoneMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (CollectionsUtil.isNotEmpty(customerIdSet)) {
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                    boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, customerIdSet));
                    List<String> fieldList = new ArrayList<>();
                    fieldList.add("data." + CustomerManagementEnum.PHONE.getAttr() + StringConstant.POINT + StringConstant.PHONE_TEL_ATTR);
                    fieldList.add(FieldTypeEnum.DATAID.getAlias());
                    IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                    List<PaasFormDataEntityExt> customerList = esHelper.findByScroll(indexTypeEnum, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                    String phone;
                    for (PaasFormDataEntityExt paasFormDataEntityExt : customerList) {
                        phone = "";
                        JSONObject data = paasFormDataEntityExt.getData();
                        if (Objects.nonNull(data)) {
                            JSONArray phoneArr = data.getJSONArray(CustomerManagementEnum.PHONE.getAttr());
                            if (phoneArr != null && !phoneArr.isEmpty()) {
                                for (int j = 0; j < phoneArr.size(); j ++) {
                                    JSONObject phoneObj = phoneArr.getJSONObject(j);
                                    if (StringUtil.isNotEmpty(phoneObj.getString(StringConstant.PHONE_TEL_ATTR))) {
                                        phone = phoneObj.getString(StringConstant.PHONE_TEL_ATTR);
                                        break;
                                    }
                                }
                            }
                        }
                        phoneMap.put(paasFormDataEntityExt.getDataId(), phone);
                    }
                }
                // 前置处理负责人和协同人
                Map<Long, Set<String>> mainUserMap = new HashMap<>();
                Map<Long, Set<String>> coUserMap = new HashMap<>();
                getMainAndCoUserMapForExport(corpid, XbbRefTypeEnum.WORK_ORDER.getCode(), excelTemplateDTO.getSaasMark(), dataIdList, mainUserMap, coUserMap, false);

                int j = 0;
                ExportLinkDataPojo exportLinkDataPojo = new ExportLinkDataPojo(formExplainMap, workOrderFormExplainMap, formDataMap);
                for (WorkOrderEntityExt workOrderEntityExt : workOrderEntityExts) {

                    // 设置协同人和负责人
                    setMainAndCoUserForExport(excelTemplateDTO.getSaasMark(), XbbRefTypeEnum.WORK_ORDER.getCode(), userAllMap, mainUserMap, coUserMap, workOrderEntityExt);
                    JSONObject formDataObj = workOrderEntityExt.getData();
                    //处理地址
                    PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
                    BeanUtil.copyProperties(workOrderEntityExt, paasFormDataEntityExt);

                    importHelper.formatCommonData4Export(userMap, deptMap, paasFormDataEntityExt, formDataObj, explainList, phoneMap, exportLinkDataPojo, businessType, null);
                    // 所有下拉框全部从改造的解释中取
                    importHelper.formatDropDown4Export(fieldAttrList, formDataObj, null);
                    //importHelper.formatWorkOrderData4Export(userMap, deptMap, paasFormDataEntityExt, formDataObj, explainList, phoneMap, null);
                    // 所有下拉框全部从改造的解释中取(工单提前解析了，所以自己写一个)
                    //importHelper.workOrderFormatDropDown4Export(fieldAttrList, formDataObj);
                    // 字段可见性判断
                    for (FieldAttrEntity fieldAttrEntity : explainList) {
                        if (ExplainUtil.isFieldNeedHide(fieldAttrEntity, handlerExplainDTO)){
                            formDataObj.put(fieldAttrEntity.getAttr(), "");
                        } else if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SUB_FORM.getType())) {
                            // 子表单也有高级权限
                            List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                            for (FieldAttrEntity subFieldAttrEntity : subExplainList) {
                                if (ExplainUtil.isFieldNeedHide(subFieldAttrEntity, handlerExplainDTO)){
                                    try {
                                        JSONArray jsonArray  = formDataObj.getJSONArray(fieldAttrEntity.getAttr());
                                        for (int k = 0; k < jsonArray.size(); k++) {
                                            JSONObject jsonObject = jsonArray.getJSONObject(k);
                                            jsonObject.put(subFieldAttrEntity.getAttr(), "");
                                        }
                                    } catch (Exception e) {
                                        LOG.error("export invisible subForm error ", e);
                                    }
                                }
                            }
                        }
                    }

                    int successNum = exportStatusPojo.getSuccessNum();
                    exportStatusPojo.setSuccessNum(++successNum);
                    // 每隔50组/数据导完时，刷新一次当前导入状态
                    if (j == 0 || j % 50 == 0) {
                        paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
                    }
                    j++;
                }
            }

            // 最后更新一次最终状态
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.COMMON_DURATION);

            formDataListDTO.setUserAllMap(userAllMap);
            formDataListDTO.setUserMap(userMap);
            formDataListDTO.setDeptMap(deptMap);
            List<PaasFormDataEntityExt> paasFormDataESList = new ArrayList<>();
            BeanUtil.copyPropertiesList(workOrderEntityExtList, paasFormDataESList, PaasFormDataEntityExt.class);
            handleImportService.formatExportValue(paasFormDataESList, formDataListDTO, fieldAttrList);
            if (RelativeProductImportEnum.exportProductBusinessTypeList().contains(businessType)) {
                Set<Object> linkDataIdSet = new HashSet<>();
                // 这个好难啊
                if (CollectionsUtil.isNotEmpty(productLinkDataAttrSet)) {
                    for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
                        JSONObject data = paasFormDataEntityExt.getData();
                        productLinkDataAttrSet.forEach(item->{
                            String[] attrArray = item.split("\\.");
                            String attr = attrArray[0];
                            JSONArray jsonArray = data.getJSONArray(attr);
                            if (CollectionsUtil.isNotEmpty(jsonArray)) {
                                for (int i = 0; i < jsonArray.size(); i++) {
                                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                                    if (jsonObject.get(attrArray[1]) instanceof Number && !Objects.equals(jsonObject.get(attrArray[1]), 0L)) {
                                        Long id = jsonObject.getLong(attrArray[1]);
                                        if (Objects.nonNull(id)) {
                                            linkDataIdSet.add(id);
                                        }
                                    }
                                }
                            }
                        });
                    }
                }
                // 获取关联数据字段所需要的数据
                LinkResultDataVO linkResultDataVO = new LinkResultDataVO();
                linkResultDataVO.setExplainMap(explainMap);
                linkResultDataVO.setLinkDataSet(linkDataIdSet);
                linkResultDataVO.setExplainList(explainList);
                Map<String, PaasFormDataEntityExt> formDataMap = linkDataHelp.getLinkDataOfBusinessType(linkResultDataDTO, linkResultDataVO);
                ExportLinkDataPojo exportLinkDataPojo = new ExportLinkDataPojo(formExplainMap, workOrderFormExplainMap, formDataMap);
                for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
                    for (FieldAttrEntity fieldAttrEntity : explainList) {
                        if (Objects.equals(fieldAttrEntity.getFieldType(), FieldTypeEnum.SELECT_PRODUCT.getType()) && Objects.equals(fieldAttrEntity.getIsOpen(), 1)) {
                            // 子表单也有高级权限
                            List<? extends FieldAttrEntity> subExplainList = fieldAttrEntity.getSubForm().getItems();
                            proFormHelp.setProductAccuracy(fieldAttrEntity, corpid, formDataListDTO.getUserId());
                            JSONArray jsonArray = paasFormDataEntityExt.getData().getJSONArray(fieldAttrEntity.getAttr()) == null ? new JSONArray() : paasFormDataEntityExt.getData().getJSONArray(fieldAttrEntity.getAttr());
                            for (FieldAttrEntity subFieldAttrEntity : subExplainList) {
                                if (Objects.equals(subFieldAttrEntity.getIsRedundant(), 1)) {
                                    try {
                                        // 产品子表单内自定义字段解析
                                        for (int i = 0; i < jsonArray.size(); i++) {
                                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                                            importHelper.formatRelativeProductData4Export(userMap, deptMap, jsonObject, subFieldAttrEntity, exportLinkDataPojo, corpid);
                                        }
                                    } catch (Exception e) {
                                        LOG.error("export customer field error ", e);
                                    }
                                } else {
                                    if (Objects.equals(subFieldAttrEntity.getFieldType(), FieldTypeEnum.NUM.getType())) {
                                        try {
                                            for (int i = 0; i < jsonArray.size(); i++) {
                                                JSONObject jsonObject = jsonArray.getJSONObject(i);
                                                if (Objects.nonNull(jsonObject.getDouble(subFieldAttrEntity.getAttr())) && Objects.equals(subFieldAttrEntity.getIntegerOnly(), 0)) {
                                                    jsonObject.put(subFieldAttrEntity.getAttr(), attrDecimalPrecisionHelper.setDecPrecision(jsonObject.getDouble(subFieldAttrEntity.getAttr()), subFieldAttrEntity.getAccuracy()));
                                                }
                                            }
                                        } catch (Exception e) {
                                            LOG.error(JSON.toJSONString(jsonArray));
                                            LOG.error("export num select product error ", e);
                                        }
                                    }else if (Objects.equals(ProductEnum.UNIT.getAttr(),  subFieldAttrEntity.getAttr()) || Objects.equals(SelectProductEnum.BASIC_UNIT.getAttr(),  subFieldAttrEntity.getAttr())){
                                        //多单位产品导出 单位栏处理
                                        for (int i = 0; i < jsonArray.size(); i++) {
                                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                                            Object itemValue = ItemUtil.getCustomItemList(subFieldAttrEntity, jsonObject);
                                            jsonObject.put(subFieldAttrEntity.getAttr(), itemValue);
                                            jsonObject.remove(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
                                        }
                                    }
                                }
                                if (ExplainUtil.isFieldNeedHide(subFieldAttrEntity, handlerExplainDTO)) {
                                    try {
                                        for (int i = 0; i < jsonArray.size(); i++) {
                                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                                            jsonObject.put(subFieldAttrEntity.getAttr(), "");
                                        }
                                    } catch (Exception e) {
                                        LOG.error("export invisible select error ", e);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.STOCK_SEARCH.getCode())) {
                menuName = XbbRefTypeEnum.STOCK_SEARCH.getName();
            } else if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.WARNING_SEARCH.getCode())) {
                menuName = XbbRefTypeEnum.WARNING_SEARCH.getName();
            } else if (Objects.equals(formDataListDTO.getSubBusinessType(), XbbRefTypeEnum.GUARANTEE_SEARCH.getCode())) {
                menuName = XbbRefTypeEnum.GUARANTEE_SEARCH.getName();
            }
            workbook = excelOperatorService.createExcel(paasFormDataESList, dataExplain, menuName, formDataListDTO);
            String excelName = menuName + DateTimeUtil.getString(DateTimeUtil.SDFDate) + ImportConstant.EXCEL_SUFFIX;
            exportFormDataVO.setWorkbook(workbook);
            exportFormDataVO.setName(excelName);

            // OSS上传文件
            handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);

        } catch (XbbException e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportWorkOrderList error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw e;
        } catch (Exception e) {
            LOG.error("paasExcel数据库导出表单数据出错", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg("导出失败!");
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        } finally {
            closeWorkBookException(workbook);
        }
        return exportFormDataVO;
    }

    public ExportFormDataVO exportOldWorkOrderList(FormDataListDTO formDataListDTO, SpecialWorkOrderExportDTO specialWorkOrderExportDTO) throws XbbException {
        ExportFormDataVO exportFormDataVO = new ExportFormDataVO();
        String hashKey = formDataListDTO.getCorpid() + "_" + formDataListDTO.getUserId();
        Workbook workbook = null;
        try {
            String corpid = formDataListDTO.getCorpid();
            ExcelTemplateDTO excelTemplateDTO = new ExcelTemplateDTO();
            BeanUtil.copyProperties(formDataListDTO, excelTemplateDTO);
            Map<String, Object> explainParam = BeanUtil.convertBean2Map(excelTemplateDTO, true);
            List<WorkOrderExplainEntity> formExplainList = workOrderExplainModel.list(explainParam);
            if (formExplainList == null || formExplainList.isEmpty()) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
            }
            WorkOrderExplainEntity workOrderExplainEntity = formExplainList.get(0);
            Long menuId = Objects.isNull(formDataListDTO.getMenuId()) ? workOrderExplainEntity.getMenuId() : formDataListDTO.getMenuId();
            PaasMenuEntity paasMenuEntity = paasMenuModel.getByKey(menuId, corpid);
            if (paasMenuEntity == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_NOT_EXIST);
            }
            List<FieldAttrEntityForImport> fieldAttrList = JSON.parseArray(workOrderExplainEntity.getExplains(), FieldAttrEntityForImport.class);
            //过滤阶段ID以及拥有者,出库完全标志也过滤，不知道哪个皮皮虾加进来了，导致测试环境上有
            Iterator<FieldAttrEntityForImport> iterator = fieldAttrList.iterator();
            while (iterator.hasNext()) {
                FieldAttrEntityForImport fieldAttrEntityForImport = iterator.next();
                if (Objects.equals(fieldAttrEntityForImport.getAttr(), WorkOrderEnum.STAGE.getAttr())) {
                    iterator.remove();
                }
                if (Objects.equals(fieldAttrEntityForImport.getAttr(), WorkOrderEnum.ALL_OUTBOUND.getAttr())) {
                    iterator.remove();
                }
                /*if(Objects.equals(fieldAttrEntityForImport.getAttr(), WorkOrderEnum.OWNER_ID.getAttr())) {
                    iterator.remove();
                }*/
            }
            // 处理关联新建表单
            if (Objects.equals(formDataListDTO.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
                LinkFormImportPojo linkFormImportPojo = new LinkFormImportPojo();
                BeanUtil.copyProperties(formDataListDTO, linkFormImportPojo);
                linkFormImportPojo.setFieldAttrEntityForImportList(fieldAttrList);
                linkFormImportPojo.setFormImportOrExport(ImportConstant.FROM_EXPORT);
                handleImportService.handleLinkForm(linkFormImportPojo, DistributorMarkEnum.OTHER.getCode());
            }
            boolean partialExportFlag = null!=formDataListDTO.getExcelPartialExportPojo()
                    && Objects.equals(formDataListDTO.getExcelPartialExportPojo().getPartialExport(),1);
            // 过滤不需要导入的字段
            handleImportService.filterUnExportFields(formDataListDTO.getCorpid(), fieldAttrList, formDataListDTO.getSaasMark(), ImportConstant.FROM_EXPORT, formDataListDTO.getBusinessType(), partialExportFlag);
            // 处理公有的需要转换的字段
            handleImportService.handleCommonNeedTransferFields(fieldAttrList, formDataListDTO);
            JSONArray dataExplain;
            if (Objects.equals(excelTemplateDTO.getSaasMark(), SaasMarkEnum.SAAS.getCode())) {
                // SaaS字段解释特处理
                excelTemplateDTO.setFormImportOrExport(ImportConstant.FROM_EXPORT);
                dataExplain = handleImportService.handleSpecialExplain(fieldAttrList, excelTemplateDTO);
            } else {
                handleImportService.setTitleTag(fieldAttrList);
                dataExplain = JSON.parseArray(JSON.toJSONString(fieldAttrList));
            }


            Map<String, Object> userMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, UserEntity> userAllMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String, Object> deptMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

            // 获取员工和部门map
            getUserMapAndDeptMap(corpid, userMap, deptMap, userAllMap);

            List<WorkOrderEntityExt> workOrderEntityExtList = specialWorkOrderExportDTO.getPaasFormDataESList();
            if (workOrderEntityExtList.isEmpty()) {
                throw new XbbException(ImportErrorCodeEnum.API_ERROR_235005);
            }
            // 先用原始解释转换一遍数据
            List<FieldAttrEntity> explainList = new ArrayList<>();
            // 为了导出关联客户的客户电话
            List<String> linkCustomerAttrList = new ArrayList<>();
            specialWorkOrderExportDTO.getExplainMap().forEach((index, item) -> {
                if (Objects.equals(item.getFieldType(), FieldTypeEnum.LINK_BUSINESS_SINGLE.getType()) && Objects.equals(item.getLinkedType(), RedundantTemplateTypeEnum.CUSTOMER.getCode())) {
                    linkCustomerAttrList.add(item.getAttr());
                }
                explainList.add(item);
            });

            int size = workOrderEntityExtList.size();
            ExportStatusPojo exportStatusPojo = new ExportStatusPojo();
            BeanUtil.copyProperties(formDataListDTO, exportStatusPojo);
            exportStatusPojo.setTotalNum(size);


            for (int i = 0; i < size; i += ExcelConstant.PER_WRITE_INSERT_BATCH_COUNT) {

                int toIndex = i + ExcelConstant.PER_WRITE_INSERT_BATCH_COUNT;
                if (toIndex > size) {
                    toIndex = size;
                }
                List<WorkOrderEntityExt> workOrderEntityExts = workOrderEntityExtList.subList(i, toIndex);
                List<Long> dataIdList = new ArrayList<>();
                Set<Long> customerIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Long linkCustomerId = 0L;
                for (WorkOrderEntityExt workOrderEntityExt : workOrderEntityExts) {
                    for (String attr : linkCustomerAttrList) {
                        try {
                            JSONArray jsonArrOrDefaultFromFormData = FastJsonHelper.getJsonArrOrDefaultFromFormData(workOrderEntityExt.getData(), attr, new JSONArray());
                            if (jsonArrOrDefaultFromFormData.size() > 0) {
                                JSONObject object = jsonArrOrDefaultFromFormData.getJSONObject(0);
                                linkCustomerId = object.getLong(BasicConstant.ID) == null ? 0L : object.getLong(BasicConstant.ID);
                            }
                        } catch (Exception e) {
                            linkCustomerId = 0L;
                        }
                        customerIdSet.add(linkCustomerId);
                    }
                    dataIdList.add(workOrderEntityExt.getId());
                }
                customerIdSet.remove(0L);
                Map<Long, String> phoneMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (CollectionsUtil.isNotEmpty(customerIdSet)) {
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                    boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, customerIdSet));
                    List<String> fieldList = new ArrayList<>();
                    fieldList.add("data." + CustomerManagementEnum.PHONE.getAttr() + StringConstant.POINT + StringConstant.PHONE_TEL_ATTR);
                    fieldList.add(FieldTypeEnum.DATAID.getAlias());

                    IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                    List<PaasFormDataEntityExt> customerList = esHelper.findByScroll(indexTypeEnum, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
                    String phone;
                    for (PaasFormDataEntityExt paasFormDataEntityExt : customerList) {
                        phone = "";
                        JSONObject data = paasFormDataEntityExt.getData();
                        if (Objects.nonNull(data)) {
                            JSONArray phoneArr = data.getJSONArray(CustomerManagementEnum.PHONE.getAttr());
                            if (phoneArr != null && !phoneArr.isEmpty()) {
                                for (int j = 0; j < phoneArr.size(); j ++) {
                                    JSONObject phoneObj = phoneArr.getJSONObject(j);
                                    if (StringUtil.isNotEmpty(phoneObj.getString(StringConstant.PHONE_TEL_ATTR))) {
                                        phone = phoneObj.getString(StringConstant.PHONE_TEL_ATTR);
                                        break;
                                    }
                                }
                            }
                        }
                        phoneMap.put(paasFormDataEntityExt.getDataId(), phone);
                    }
                }
                // 前置处理负责人和协同人
                Map<Long, Set<String>> mainUserMap = new HashMap<>();
                Map<Long, Set<String>> coUserMap = new HashMap<>();
                getMainAndCoUserMapForExport(corpid, XbbRefTypeEnum.WORK_ORDER.getCode(), excelTemplateDTO.getSaasMark(), dataIdList, mainUserMap, coUserMap, false);

                int j = 0;
                for (WorkOrderEntityExt workOrderEntityExt : workOrderEntityExts) {
                    //处理负责人
//                String owner = formDataObj.getString(WorkOrderEnum.OWNER_ID.getAttr());
//                List<Object> ownerIdIn = Collections.singletonList(userMap.get(owner));
//                formDataObj.put(WorkOrderEnum.OWNER_ID.getAttr(), ownerIdIn);
//                //处理协同人
//                String coUser = formDataObj.getString(WorkOrderEnum.COUSERID.getAttr());
//                String[] coUserStrIn = coUser.split("、");
//                List<Object> coUserIn = new ArrayList<>();
//                for (String coUserStr : coUserStrIn) {
//                    coUserIn.add(userMap.get(coUserStr));
//                }
//                formDataObj.put(WorkOrderEnum.COUSERID.getAttr(), coUserIn);

                    // 设置协同人和负责人
                    setMainAndCoUserForExport(excelTemplateDTO.getSaasMark(), XbbRefTypeEnum.WORK_ORDER.getCode(), userAllMap, mainUserMap, coUserMap, workOrderEntityExt);
                    JSONObject formDataObj = workOrderEntityExt.getData();
                    //处理地址
                    PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
                    BeanUtil.copyProperties(workOrderEntityExt, paasFormDataEntityExt);
                    importHelper.formatWorkOrderData4Export(userMap, deptMap, paasFormDataEntityExt, formDataObj, explainList, phoneMap, null, formDataListDTO.getBusinessType());
                    // 所有下拉框全部从改造的解释中取(工单提前解析了，所以自己写一个)
                    importHelper.workOrderFormatDropDown4Export(fieldAttrList, formDataObj);

                    int successNum = exportStatusPojo.getSuccessNum();
                    exportStatusPojo.setSuccessNum(++successNum);
                    // 每隔50组/数据导完时，刷新一次当前导入状态
                    if (j == 0 || j % 50 == 0) {
                        paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
                    }
                    j++;
                }
            }
            // 最后更新一次最终状态
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.COMMON_DURATION);

            formDataListDTO.setUserMap(userMap);
            formDataListDTO.setDeptMap(deptMap);
            List<PaasFormDataEntityExt> paasFormDataESList = new ArrayList<>();
            BeanUtil.copyPropertiesList(workOrderEntityExtList, paasFormDataESList, PaasFormDataEntityExt.class);
            handleImportService.formatExportValue(paasFormDataESList, formDataListDTO, fieldAttrList);
            workbook = excelOperatorService.createExcel(paasFormDataESList, dataExplain, paasMenuEntity.getName(), formDataListDTO);
            String excelName = paasMenuEntity.getName() + DateTimeUtil.getString(DateTimeUtil.SDFDate) + ImportConstant.EXCEL_SUFFIX;
            exportFormDataVO.setWorkbook(workbook);
            exportFormDataVO.setName(excelName);

            formDataListDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
            // OSS上传文件
            handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);

        } catch (XbbException e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportWorkOrderList error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw e;
        } catch (Exception e) {
            LOG.error("paasExcel数据库导出表单数据出错", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        } finally {
            closeWorkBookException(workbook);
        }
        return exportFormDataVO;
    }


    /**
     * 签到excel
     *
     * @param signExportDTO 入参
     * @param signInExportDTO
     */
    @Async(value = "exportThreadPool")
    public void exportSignList(SignExportDTO signExportDTO, SignInExportDTO signInExportDTO) throws XbbException {
        String[] split = signExportDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        ExportFormDataVO exportFormDataVO = new ExportFormDataVO();
        String hashKey = signExportDTO.getCorpid() + "_" + signExportDTO.getUserId();
        Workbook workbook = null;
        try {
            String[] colTitle = I18nMessageUtil.getMessages(I18nStringConstant.SIGN_LIST_TITLE).toArray(new String[6]);
            workbook = excelOperatorService.createEmptyExcel4MoreTitle(10, I18nMessageUtil.getMessage(I18nStringConstant.SIGN_RECORD), colTitle, null);
            Map<String, Integer> indexMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            indexMap.put("orderNumber", 0);
            indexMap.put("userName", 1);
            indexMap.put("addTime", 2);
            indexMap.put("customerName", 3);
            indexMap.put("formatAddress", 4);
            indexMap.put("memo", 5);
            Sheet sheet = workbook.getSheetAt(0);
            List<SignInEntityExt> signList = signExportDTO.getSignList();
            int lastRowNum = sheet.getLastRowNum();
            // 导出状态
            int totalRowNum = signList.size();
            ExportStatusPojo exportStatusPojo = new ExportStatusPojo();
            BeanUtil.copyProperties(signExportDTO, exportStatusPojo);
            exportStatusPojo.setTotalNum(totalRowNum);

            Row row;
            SignInEntityExt signInEntityExt;
            for (int i = 0; i < signList.size(); i++) {
                // 每隔50条/数据导完时，刷新一次当前导入状态
                if (i == 0 || i % 50 == 0) {
                    paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY,hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
                }
                row = sheet.createRow(i + lastRowNum + 1);
                signInEntityExt = signList.get(i);
                for (Map.Entry<String, Integer> entry : indexMap.entrySet()) {
                    Integer index = entry.getValue();
                    String attr = entry.getKey();
                    if(Objects.equals(attr, "orderNumber")){
                        row.createCell(index).setCellValue(row.getRowNum());
                    } else if (Objects.equals(attr, "addTime")) {
                        row.createCell(index).setCellValue(DateTimeUtil.getStringEpochSecond(signInEntityExt.getAddTime(), new SimpleDateFormat("yyyy-MM-dd HH:mm")));
                    } else{
                        Object value = ReflectHelper.valueGet(signInEntityExt, attr, true);
                        row.createCell(index).setCellValue(Objects.isNull(value) ? "" : value.toString());
                    }
                }

                int successNum = exportStatusPojo.getSuccessNum();
                exportStatusPojo.setSuccessNum(++successNum);

            }
            // 最后更新一次最终状态
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.COMMON_DURATION);
            exportFormDataVO.setWorkbook(workbook);
            String excelName = I18nMessageUtil.getMessage(I18nStringConstant.SIGN_RECORD) + DateTimeUtil.getString(DateTimeUtil.SDFDate) + ImportConstant.EXCEL_SUFFIX;
            exportFormDataVO.setName(excelName);
            // OSS上传文件
            FormDataListDTO formDataListDTO = new FormDataListDTO();
            BeanUtil.copyProperties(signInExportDTO, formDataListDTO);
            handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);
        } catch (XbbException e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportSignList error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw e;
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportSignList error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        } finally {
            closeWorkBookException(workbook);
        }
    }

    /**
     * 客户对账单excel
     *
     * @param customerStatementExportDTO 入参
     */
    @Async(value = "exportThreadPool")
    public void exportCustomerStatementList(CustomerStatementExportDTO customerStatementExportDTO) throws XbbException {
        String[] split = customerStatementExportDTO.getLocale().split("_");
        LocaleContextHolder.setLocale(new Locale(split[0], split[1]));
        ExportFormDataVO exportFormDataVO = new ExportFormDataVO();
        String hashKey = customerStatementExportDTO.getCorpid() + "_" + customerStatementExportDTO.getUserId();
        Workbook workbook = null;
        try {
            List<KeyValuePojo> title = customerStatementExportDTO.getTitle();
            //字段名-索引
            Map<String, Integer> indexMap = new LinkedHashMap<>(32);
            int index = 0;
            for (int i = 0; i < title.size(); i++) {
                KeyValuePojo keyValuePojo = title.get(i);
                indexMap.put(keyValuePojo.getKey(), i + index);
                if (Objects.equals(keyValuePojo.getAttr(), CustomerStatementEnum.PRODUCT.getAttr())) {
                    // 产品展示字段固定为6个
                    index = 5;
                }
            }
            List<List<List<Object>>> titleList = new LinkedList<>();
            int level = 1;
            for (KeyValuePojo keyValuePojo : title) {
                List<List<Object>> titleField = new LinkedList<>();
                if (CollectionsUtil.isNotEmpty(keyValuePojo.getProducts())) {
                    level = 2;
                    titleField.add(Collections.singletonList(keyValuePojo.getValue()));
                    List<Object> products = new ArrayList<>();
                    for (KeyValuePojo productPojo : keyValuePojo.getProducts()) {
                        products.add(productPojo.getValue());
                    }
                    titleField.add(products);
                } else {
                    titleField.add(Collections.singletonList(keyValuePojo.getValue()));
                }
                titleList.add(titleField);
            }
            workbook = excelOperatorService.createStatementExcelWithHead(I18nMessageUtil.getMessage(I18nStringConstant.CUSTOMER_STATEMENT_RECORD), titleList, level);
            Sheet sheet = workbook.getSheetAt(0);
            List<StatementTableDataExportPojo> exportDataList = customerStatementExportDTO.getExportData();
            int lastRowNum = sheet.getLastRowNum();
            // 导出状态
            int totalRowNum = exportDataList.size();
            ExportStatusPojo exportStatusPojo = new ExportStatusPojo();
            BeanUtil.copyProperties(customerStatementExportDTO, exportStatusPojo);
            exportStatusPojo.setTotalNum(totalRowNum);

            for (int i = 0; i < exportDataList.size(); i++) {
                // 每隔50条/数据导完时，刷新一次当前导入状态
                if (i == 0 || i % 50 == 0) {
                    paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY,hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
                }
                Row row = sheet.createRow(i + lastRowNum + 1);
                StatementTableDataExportPojo tableDataExportPojo = exportDataList.get(i);
                for (Map.Entry<String, Integer> entry : indexMap.entrySet()) {
                    Integer temp = entry.getValue();
                    String attr = entry.getKey();
                    Object value = ReflectHelper.valueGet(tableDataExportPojo, attr, true);
                    if (Objects.equals(attr, CustomerStatementEnum.PRODUCT.getAttr())) {
                        // 关联产品
                        if (value instanceof JSONArray) {
                            JSONArray products = (JSONArray) value;
                            if (CollectionsUtil.isNotEmpty(products)) {
                                for (int j = 0; j < products.size(); j++) {
                                    JSONObject product = products.getJSONObject(j);
                                    if (j > 0) {
                                        row = sheet.createRow(i + lastRowNum + 1);
                                    }
                                    row.createCell(temp).setCellValue(product.getString(SelectProductEnum.PRODUCT_NAME.getAttr()));
                                    row.createCell(temp + 1).setCellValue(product.getString(SelectProductEnum.PRODUCT_NO.getAttr()));
                                    row.createCell(temp + 2).setCellValue(product.getString(SelectProductEnum.SPECIFICATION.getAttr()));
                                    row.createCell(temp + 3).setCellValue(product.getDoubleValue(SelectProductEnum.SELLING_PRICE.getAttr()));
                                    row.createCell(temp + 4).setCellValue(product.getDoubleValue(SelectProductEnum.NUM.getAttr()));
                                    row.createCell(temp + 5).setCellValue(product.getDoubleValue(SelectProductEnum.SUBTOTAL.getAttr()));
                                    lastRowNum++;
                                }
                                lastRowNum--;
                            }
                        }
                    } else {
                        row.createCell(temp).setCellValue(Objects.isNull(value) ? "" : value.toString());
                    }
                }

                int successNum = exportStatusPojo.getSuccessNum();
                exportStatusPojo.setSuccessNum(++successNum);

            }
            // 最后更新一次最终状态
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.COMMON_DURATION);
            exportFormDataVO.setWorkbook(workbook);
            //拼excel名称
            List<Long> checkingDate = customerStatementExportDTO.getCheckingDate();
            StringBuilder excelName = new StringBuilder();
            excelName.append(customerStatementExportDTO.getCustomerName());
            excelName.append(DateTimeUtil.getStringEpochSecond(checkingDate.get(0), DateTimeUtil.SDFDate));
            excelName.append("至");
            excelName.append(DateTimeUtil.getStringEpochSecond(checkingDate.get(1), DateTimeUtil.SDFDate));
            excelName.append(I18nMessageUtil.getMessage(I18nStringConstant.CUSTOMER_STATEMENT_RECORD));
            excelName.append(ImportConstant.EXCEL_SUFFIX);
            exportFormDataVO.setName(excelName.toString());
            // OSS上传文件
            FormDataListDTO formDataListDTO = new FormDataListDTO();
            BeanUtil.copyProperties(customerStatementExportDTO, formDataListDTO);
            handleImportService.exportAsync(formDataListDTO, exportFormDataVO, ImportConstant.EXCEL_SUFFIX);
        } catch (XbbException e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportCustomerStatementList error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw e;
        } catch (Exception e) {
            LOG.error("com.xbongbong.paas.help.PaasExcelExportHelp.exportCustomerStatementList error", e);
            ExportStatusPojo exportStatusPojo = JsonHelperUtil.parseObject(Objects.toString(paasRedisHelper.getValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey), JSON.toJSONString(new ExportStatusPojo())), ExportStatusPojo.class);
            exportStatusPojo.setFinish(1);
            exportStatusPojo.setErrorMsg(I18nMessageUtil.getMessage(I18nStringConstant.EXPORT_FAILED));
            paasRedisHelper.setValue(RedisPrefixConstant.EXPORT_STATUS_KEY, hashKey, exportStatusPojo, RedisConstant.SHORT_DURATION);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        } finally {
            closeWorkBookException(workbook);
        }
    }



    /**
     * 获取员工和部门map
     *
     * @param corpid 公司id
     * @param userMap 员工map
     * @param deptMap 部门map
     */
    private void getUserMapAndDeptMap(String corpid, Map<String, Object> userMap, Map<String, Object> deptMap,  Map<String, UserEntity> userAllMap) {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, corpid);
        params.put(ParameterConstant.LEAVE_MARKS, BasicConstant.ONE);
        List<UserEntity> userEntityList = userModel.findEntitys(params);

        for (UserEntity userEntity : userEntityList) {
            userMap.put(userEntity.getUserId(), userEntity.getName());
            userAllMap.put(userEntity.getUserId(), userEntity);
        }

        // deptMap key是部门名称路由
        params.remove(ParameterConstant.LEAVE_MARKS);
        params.remove(ParameterConstant.COLUMNS);
        List<DepartmentEntity> departmentList = departmentModel.findEntitys(params);

        Map<String, DepartmentEntity> departmentMap = new HashMap<>(departmentList.size());
        departmentList.forEach(item -> departmentMap.put(item.getId().toString(), item));
        for (DepartmentEntity departmentEntity : departmentList) {
            StringBuilder stringBuilder = new StringBuilder();
            String[] routerArr = departmentEntity.getDepIdRouter().split("\\|");
            for (int i = 0; i < routerArr.length; i++) {
                String deptId = routerArr[i];
                if (StringUtil.isNotEmpty(deptId) && departmentMap.containsKey(deptId)) {
                    String name = departmentMap.get(deptId).getName();
                    stringBuilder.append(name).append(PaasConstant.ROLE_DELIMITER);
                }
            }
            if (stringBuilder.length() > 0) {
                deptMap.put(departmentEntity.getId().toString(),stringBuilder.substring(0, stringBuilder.length() - 1));
            }
        }
    }


    /**
     * 获取 可见范围Team （产品、服务项目）
     * @param corpid
     * @param businessType
     * @param dataIdList
     * @return
     * @throws XbbException
     */
    public Map<Long, List<UserAndDepTeamEntity>> getVisibleRangeUserTeam(String corpid, Integer businessType, List<Long> dataIdList) throws XbbException {
        Map<Long, List<UserAndDepTeamEntity>> teamMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if  (Objects.equals(businessType, XbbRefTypeEnum.PRODUCT.getCode())) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery(SubFormTransferEnum.getEsAttrByIndexTypeAndDbAttr(UserTeamEnum.PRODUCT_TEAM.getIndexTypeEnum(), StringConstant.DATA_ID), dataIdList));
            List<PaasFormDataEntity> teamEntityList = esHelper.findByScroll(UserTeamEnum.PRODUCT_TEAM.getIndexTypeEnum(), boolQueryBuilder, PaasFormDataEntity.class, null);
            List<UserAndDepTeamEntity> teamList = transferSubFormHelper.transferFormDataToUserAndDepTeam(UserTeamEnum.PRODUCT_TEAM.getIndexTypeEnum(), teamEntityList);
            teamList.forEach(userAndDepTeamEntity -> {
                List<UserAndDepTeamEntity> singleTeamList = new ArrayList<>();
                if (teamMap.containsKey(userAndDepTeamEntity.getDataId())) {
                    singleTeamList = teamMap.get(userAndDepTeamEntity.getDataId());
                }
                singleTeamList.add(userAndDepTeamEntity);
                teamMap.put(userAndDepTeamEntity.getDataId(), singleTeamList);
            });
        } else if (Objects.equals(businessType, XbbRefTypeEnum.SERVICE_PROJECT.getCode())) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery(SubFormTransferEnum.getEsAttrByIndexTypeAndDbAttr(UserTeamEnum.SERVICE_PROJECT_TEAM.getIndexTypeEnum(), StringConstant.DATA_ID), dataIdList));
            List<PaasFormDataEntity> teamEntityList = esHelper.findByScroll(UserTeamEnum.SERVICE_PROJECT_TEAM.getIndexTypeEnum(), boolQueryBuilder, PaasFormDataEntity.class, null);
//            List<UserAndDepTeamEntity> teamList = transferSubFormHelper.transferFormDataToUserAndDepTeam(UserTeamEnum.SERVICE_PROJECT_TEAM.getIndexTypeEnum(), teamEntityList);
            //todo-leex 以下先随意搬一下，晚点写 可见范围共用。
            List<UserAndDepTeamEntity> teamList = new ArrayList<>();
            for (PaasFormDataEntity paasFormDataEntity : teamEntityList) {
                UserAndDepTeamEntity userAndDepTeamEntity = transferFormDataToTeam(paasFormDataEntity);
                teamList.add(userAndDepTeamEntity);
            }

            teamList.forEach(userAndDepTeamEntity -> {
                List<UserAndDepTeamEntity> singleTeamList = new ArrayList<>();
                if (teamMap.containsKey(userAndDepTeamEntity.getDataId())) {
                    singleTeamList = teamMap.get(userAndDepTeamEntity.getDataId());
                }
                singleTeamList.add(userAndDepTeamEntity);
                teamMap.put(userAndDepTeamEntity.getDataId(), singleTeamList);
            });
        }
        return teamMap;
    }

    /**
     * 获取竞争对手可见人可见部门
     * @param corpid
     * @param businessType
     * @param dataIdList
     * @return
     * @throws XbbException
     */
    public Map<Long, List<UserAndDepTeamEntity>> getCompetitorUserTeam(String corpid, Integer businessType, List<Long> dataIdList) throws XbbException {
        Map<Long, List<UserAndDepTeamEntity>> teamMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if  (Objects.equals(businessType, XbbRefTypeEnum.COMPETITOR.getCode())) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery(SubFormTransferEnum.getEsAttrByIndexTypeAndDbAttr(UserTeamEnum.COMPETITOR_TEAM.getIndexTypeEnum(), StringConstant.DATA_ID), dataIdList));
            List<PaasFormDataEntity> teamEntityList = esHelper.findByScroll(UserTeamEnum.COMPETITOR_TEAM.getIndexTypeEnum(), boolQueryBuilder, PaasFormDataEntity.class, null);
            List<UserAndDepTeamEntity> teamList = transferSubFormHelper.transferFormDataToUserAndDepTeam(UserTeamEnum.COMPETITOR_TEAM.getIndexTypeEnum(), teamEntityList);
            teamList.forEach(userAndDepTeamEntity -> {
                List<UserAndDepTeamEntity> singleTeamList = new ArrayList<>();
                if (teamMap.containsKey(userAndDepTeamEntity.getDataId())) {
                    singleTeamList = teamMap.get(userAndDepTeamEntity.getDataId());
                }
                singleTeamList.add(userAndDepTeamEntity);
                teamMap.put(userAndDepTeamEntity.getDataId(), singleTeamList);
            });
        }
        return teamMap;
    }

    private UserAndDepTeamEntity transferFormDataToTeam(PaasFormDataEntity paasFormDataEntity) {
        JSONObject data = paasFormDataEntity.getData();

        JSONObject dbData = new JSONObject();
        VisibleRangeTeamEnum[] serviceProjectTeamEnums = VisibleRangeTeamEnum.values();
        for (VisibleRangeTeamEnum serviceProjectTeamEnum : serviceProjectTeamEnums) {
            String dbAttr = serviceProjectTeamEnum.getDbAttr();
            String dataAttr = serviceProjectTeamEnum.getDataAttr();
            Integer fieldType = serviceProjectTeamEnum.getFieldType();
            formatDataForDb(data, dbData, dbAttr, dataAttr, fieldType);
        }
        UserAndDepTeamEntity serviceProjectUserEntity = JSON.parseObject(dbData.toJSONString(), UserAndDepTeamEntity.class);
        serviceProjectUserEntity.setAddTime(paasFormDataEntity.getAddTime());
        serviceProjectUserEntity.setUpdateTime(paasFormDataEntity.getUpdateTime());
        serviceProjectUserEntity.setCorpid(paasFormDataEntity.getCorpid());
        serviceProjectUserEntity.setDel(paasFormDataEntity.getDel());
        serviceProjectUserEntity.setId(paasFormDataEntity.getId());
        return serviceProjectUserEntity;
    }

    private void formatDataForDb(JSONObject data, JSONObject dbData, String dbAttr, String dataAttr, Integer fieldType) {
        if (Objects.isNull(data)) {
            return;
        }
        FieldTypeEnum fieldTypeEnum = FieldTypeEnum.getFieldTypeEnum(fieldType);
        if (Objects.nonNull(fieldTypeEnum)) {
            Object value = data.get(dataAttr);
            if (Objects.nonNull(value)) {
                switch (fieldTypeEnum) {
                    case TEXT:
                        dbData.put(dbAttr, value.toString());
                        break;
                    case LONG:
                        dbData.put(dbAttr, Long.valueOf(value.toString()));
                        break;
                    case NUM:
                        if (value instanceof Double || value instanceof BigDecimal) {
                            dbData.put(dbAttr, value);
                        } else {
                            dbData.put(dbAttr, Long.valueOf(value.toString()));
                        }
                        break;
                    case DATETIME:
                        dbData.put(dbAttr, Long.valueOf(value.toString()));
                        break;
                    default:
                }
            }
        }
    }


    /**
     * Description: 获取各业务的负责人和协同人，前置获取（导出用）
     * @param corpid
     * @param businessType
     * @param saasMark
     * @param dataIdList
     * @param mainUserMap
     * @param coUserMap
     * @param isPublic
     * @author 魏荣杰
     * @date 2019/12/24 8:02 下午
     * @since v4.9.0
     */
    private void getMainAndCoUserMapForExport(String corpid, Integer businessType, Integer saasMark, List<Long> dataIdList, Map<Long, Set<String>> mainUserMap, Map<Long, Set<String>> coUserMap, boolean isPublic) {
        UserTeamEnum userTeamEnum = UserTeamEnum.getByCode(businessType);
        if (!Objects.equals(UserTeamEnum.UNKNOW, userTeamEnum)) {
            List<UserTeamEntity> mainUserTeamList = userTeamHelp.getUserTeamList(dataIdList, corpid, businessType, isPublic, 1);
            for (UserTeamEntity userTeamEntity : mainUserTeamList) {
                Long dataId = userTeamEntity.getDataId();
                Set<String> ids = mainUserMap.getOrDefault(dataId, new HashSet<>());
                ids.add(userTeamEntity.getUserId());
                mainUserMap.put(dataId, ids);
            }
        }
        List<UserTeamEntity> coUserTeamList = userTeamHelp.getUserTeamList(dataIdList, corpid, businessType, false, 0);
        for (UserTeamEntity userTeamEntity : coUserTeamList) {
            Long dataId = userTeamEntity.getDataId();
            Set<String> ids = coUserMap.getOrDefault(dataId, new HashSet<>());
            ids.add(userTeamEntity.getUserId());
            coUserMap.put(dataId, ids);
        }
    }


    /**
     * 解析可见人，可见部门(产品、服务项目)
     * @param teamMap
     * @param businessType
     * @param paasFormDataEntityExt
     */
    public void handleVisibleUserTeam(Map<Long, List<UserAndDepTeamEntity>> teamMap, Integer businessType, PaasFormDataEntityExt paasFormDataEntityExt) {
        if (XbbRefTypeEnum.hasVisibleRangeBusiness().contains(businessType)) {
            List<String> userIdIn = new ArrayList<>();
            List<Long> deptIdIn = new ArrayList<>();
            List<UserAndDepTeamEntity> userAndDepTeamEntities = teamMap.getOrDefault(paasFormDataEntityExt.getDataId(), new ArrayList<>());
            for (UserAndDepTeamEntity userAndDepTeamEntity : userAndDepTeamEntities) {
                if (Objects.equals(userAndDepTeamEntity.getType(), 0)) {
                    userIdIn.add(userAndDepTeamEntity.getRelationId());
                }else if (Objects.equals(userAndDepTeamEntity.getType(), 1)) {
                    deptIdIn.add(Long.parseLong(userAndDepTeamEntity.getRelationId()));
                }
            }
            paasFormDataEntityExt.getData().put(VisibleRangeEnum.VISIBLE_DEPT.getAttr(), deptIdIn);
            paasFormDataEntityExt.getData().put(VisibleRangeEnum.VISIBLE_USER.getAttr(), userIdIn);
        }
    }

    /**
     * 解析竞争对手可见人，可见部门
     * @param teamMap
     * @param businessType
     * @param paasFormDataEntityExt
     */
    public void handleCompetitorUserTeam(Map<Long, List<UserAndDepTeamEntity>> teamMap, Integer businessType, PaasFormDataEntityExt paasFormDataEntityExt) {
        if (Objects.equals(businessType, XbbRefTypeEnum.COMPETITOR.getCode())) {
            List<String> userIdIn = new ArrayList<>();
            List<Long> deptIdIn = new ArrayList<>();
            List<UserAndDepTeamEntity> userAndDepTeamEntities = teamMap.getOrDefault(paasFormDataEntityExt.getDataId(), new ArrayList<>());
            for (UserAndDepTeamEntity userAndDepTeamEntity : userAndDepTeamEntities) {
                if (Objects.equals(userAndDepTeamEntity.getType(), 0)) {
                    userIdIn.add(userAndDepTeamEntity.getRelationId());
                }else if (Objects.equals(userAndDepTeamEntity.getType(), 1)) {
                    deptIdIn.add(Long.parseLong(userAndDepTeamEntity.getRelationId()));
                }
            }
            paasFormDataEntityExt.getData().put(CompetitorEnum.VISBLE_DEPT.getAttr(), deptIdIn);
            paasFormDataEntityExt.getData().put(CompetitorEnum.VISBLE_USER.getAttr(), userIdIn);
        }
    }

    /**
     * Description: 设置负责人和协同人，用于导出
     * @param saasMark
     * @param businessType
     * @param userMap
     * @param mainUserMap
     * @param coUserMap
     * @param paasFormDataEntityExt
     * @author 魏荣杰
     * @date 2019/12/24 8:08 下午
     * @since v4.9.0
     */
    private void setMainAndCoUserForExport(Integer saasMark, Integer businessType, Map<String, UserEntity> userMap, Map<Long, Set<String>> mainUserMap, Map<Long, Set<String>> coUserMap, PaasFormDataEntityExt paasFormDataEntityExt) {
        JSONObject data = paasFormDataEntityExt.getData();
        String ownerId = paasFormDataEntityExt.getOwnerId();
        Long dataId = paasFormDataEntityExt.getId();
        // 负责人
        UserTeamEnum userTeamEnum = UserTeamEnum.getByCode(businessType);
        List<String> ownerIdList = new ArrayList<>();
        if (userTeamEnum == UserTeamEnum.UNKNOW) {
            ownerIdList.add(ownerId);
        } else {
            ownerIdList.addAll(mainUserMap.getOrDefault(dataId, new HashSet<>()));
        }
        Map<String, Object> delUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        userMap.values().forEach(userEntity -> {
            if (!Objects.equals(userEntity.getDel(), DelEnum.NORMAL.getDel())) {
                delUserMap.put(userEntity.getUserId(), userEntity);
            }
        });
        data.put(FieldTypeEnum.OWNERID.getAlias(), ownerIdList);

        List<String> coUserIdList = new ArrayList<>();
        coUserIdList.addAll(coUserMap.getOrDefault(dataId, new HashSet<>()));
        data.put(FieldTypeEnum.COUSERID.getAlias(), coUserIdList);
    }


    /**
     * 关闭workbook
     * @param workbook
     */
    public static void closeWorkBookException( Workbook workbook) {
        if (Objects.nonNull(workbook)) {
            try {
               if (workbook instanceof SXSSFWorkbook){
                    ((SXSSFWorkbook) workbook).dispose();
                }
                workbook.close();
            } catch (IOException e) {
                LOG.error("关闭workbook错误", e);
            }catch (Exception e) {
                LOG.error("关闭workbook错误", e);
            }
        }
    }

    /**
     * 解析子表单中的附件和图片字段内容
     * @param fieldAttrEntity
     * @param paasFormDataEntityExt
     */
    public void analysisSubFormFile(FieldAttrEntity fieldAttrEntity, PaasFormDataEntityExt paasFormDataEntityExt) {
        if (Objects.nonNull(fieldAttrEntity.getSubForm()) && Objects.nonNull(fieldAttrEntity.getSubForm().getItems())) {
            for (FieldAttrEntity item : fieldAttrEntity.getSubForm().getItems()) {
                if ((Objects.equals(item.getFieldType(), FieldTypeEnum.UPLOAD.getType()) || Objects.equals(item.getFieldType(), FieldTypeEnum.IMAGE.getType())) && Objects.equals(item.getIsOpen(), 1)) {
                    JSONArray subFormArray = paasFormDataEntityExt.getData().getJSONArray(fieldAttrEntity.getAttr());
                    if (Objects.isNull(subFormArray)) {
                        continue;
                    }
                    for (int j = 0; j < subFormArray.size(); j++) {
                        JSONObject rawJson = subFormArray.getJSONObject(j);
                        JSONArray fileArray = JSONObject.parseArray(rawJson.getString(item.getAttr()));
                        StringBuilder exortFile = new StringBuilder();
                        if (Objects.nonNull(fileArray)) {
                            for (int i = 1; i <= fileArray.size(); i++) {
                                if (i != 1) {
                                    exortFile.append('\n');
                                }
                                if (Objects.equals(item.getFieldType(), FieldTypeEnum.IMAGE.getType())) {
                                    exortFile.append(i).append(".").append('\n').append("(").append(fileArray.getString(i - 1)).append(")");
                                } else {
                                    JSONObject fileJson = fileArray.getJSONObject(i - 1);
                                    exortFile.append(i).append(".").append(fileJson.getString("filename")).append('\n').append("(").append(fileJson.getString("attachIndex")).append(")");
                                }
                            }
                            rawJson.put(item.getAttr(), exortFile);
                        }
                    }

                }
            }
        }
    }


}
